File: Main.hs

package info (click to toggle)
haskell-reactive-banana 1.3.2.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 412 kB
  • sloc: haskell: 3,151; makefile: 2
file content (83 lines) | stat: -rw-r--r-- 2,957 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NumericUnderscores #-}
module Main ( main ) where

import Control.Monad (replicateM, replicateM_, forM_)
import qualified Data.IntMap.Strict as IM
import Reactive.Banana.Combinators ( Event, Behavior, MonadMoment, filterE, accumE, switchB, accumB )
import Reactive.Banana.Frameworks (MomentIO, newAddHandler, fromAddHandler, compile, actuate, Handler, reactimate)
import Reactive.Banana ( Event, Behavior, MonadMoment )
import System.Random (randomRIO)
import Test.Tasty (withResource)
import Test.Tasty.Bench (env, defaultMain, bgroup, bench, whnfIO)

main :: IO ()
main = defaultMain $ [ mkBenchmarkGroup netsize | netsize <- [ 1, 2, 4, 8, 16, 32, 64, 128 ] ] ++
                     [ boringBenchmark ]
  where
    mkBenchmarkGroup netsize =
      withResource (setupBenchmark netsize) mempty $ \getEnv ->
        bgroup ("netsize = " <> show netsize)
          [ mkBenchmark getEnv steps | steps <- [ 1, 2, 4, 8, 16, 32, 64, 128] ]
      where
        mkBenchmark getEnv duration = bench ("duration = " <> show duration) $ whnfIO $ do
          (triggers, clock) <- getEnv
          let trigMap = IM.fromList $ zip [0..netsize-1] triggers
          forM_ [1..duration] $ \step -> do
            randomRs <- replicateM 10 $ randomRIO (0,netsize-1)
            clock step
            forM_ randomRs $ \ev ->
                maybe (error "benchmark: trigger not found") ($ ()) $
                    IM.lookup ev trigMap

    boringBenchmark = withResource setup mempty $ \getEnv ->
      bench "Boring" $ whnfIO $ do
        tick <- getEnv
        {-# SCC ticks #-} replicateM_ 1_000_000 $ {-# SCC tick #-} tick ()
      where
        setup = do
          (tick, onTick) <- newAddHandler
          network <- compile $ do
            e <- fromAddHandler tick
            reactimate $ return <$> e
          actuate network
          return onTick

setupBenchmark :: Int -> IO ([Handler ()], Handler Int)
setupBenchmark netsize = do
  (handlers, triggers) <- unzip <$> replicateM netsize newAddHandler
  (clock   , trigger ) <- newAddHandler

  let networkD :: MomentIO ()
      networkD = do
          es :: [Event ()] <-
            mapM fromAddHandler handlers

          e :: Event Int <-
            fromAddHandler clock

          countBs :: [Behavior Int] <-
            traverse count es

          let
            step10E :: Event Int
            step10E = filterE (\cnt -> cnt `rem` 10 == 0) e

          selectedB_E :: Event (Behavior Int) <- do
            fmap head <$> accumE countBs (keepTail <$ step10E)

          selectedB :: Behavior Int <-
            switchB (head countBs) selectedB_E

          return ()

      count :: MonadMoment m => Event () -> m (Behavior Int)
      count e = accumB 0 ((+1) <$ e)

  actuate =<< compile networkD
  return (triggers, trigger)
  where
    keepTail :: [a] -> [a]
    keepTail (_:y:zs) = y:zs
    keepTail [x]      = [x]
    keepTail []       = []