-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce allocations for event dispatch #243
base: master
Are you sure you want to change the base?
Changes from all commits
832aba2
d1ee154
4a60b22
bfe5aa5
df1b58d
5a33f4a
3ee56fa
3d9160c
d44cb98
d4021c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
reactive-banana | ||
------------------------------------------------------------------------------} | ||
{-# LANGUAGE RecordWildCards #-} | ||
{-# LANGUAGE BangPatterns #-} | ||
module Reactive.Banana.Prim.Evaluation ( | ||
step | ||
) where | ||
|
@@ -107,14 +108,14 @@ insertNodes :: RWS.Tuple BuildR (EvalPW, BuildW) Lazy.Vault -> [SomeNode] -> Que | |
insertNodes (RWS.Tuple (time,_) _ _) = go | ||
where | ||
go :: [SomeNode] -> Queue SomeNode -> IO (Queue SomeNode) | ||
go [] q = return q | ||
go (node@(P p):xs) q = do | ||
go [] !q = return q | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a big reduction in allocations, perhaps the biggest in this branch. I think we could replace |
||
go (node@(P p):xs) !q = do | ||
Pulse{..} <- readRef p | ||
if time <= _seenP | ||
then go xs q -- pulse has already been put into the queue once | ||
else do -- pulse needs to be scheduled for evaluation | ||
put p $! (let p = Pulse{..} in p { _seenP = time }) | ||
go xs (Q.insert _levelP node q) | ||
go (node:xs) q = go xs (Q.insert ground node q) | ||
go (node:xs) !q = go xs (Q.insert ground node q) | ||
-- O and L nodes have only one parent, so | ||
-- we can insert them at an arbitrary level |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,7 +39,7 @@ newInput = mdo | |
} | ||
-- Also add the alwaysP pulse to the inputs. | ||
let run :: a -> Step | ||
run a = step ([P pulse, P always], Lazy.insert key (Just a) Lazy.empty) | ||
run a n = step ([P pulse, P always], Lazy.insert key (Just a) Lazy.empty) n | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This eta expansion allows |
||
return (pulse, run) | ||
|
||
-- | Register a handler to be executed whenever a pulse occurs. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
reactive-banana | ||
------------------------------------------------------------------------------} | ||
{-# LANGUAGE RecordWildCards, RecursiveDo, ScopedTypeVariables #-} | ||
{-# LANGUAGE BangPatterns #-} | ||
module Reactive.Banana.Prim.Plumbing where | ||
|
||
import Control.Monad (join) | ||
|
@@ -129,20 +130,21 @@ addOutput p = do | |
Build monad | ||
------------------------------------------------------------------------------} | ||
runBuildIO :: BuildR -> BuildIO a -> IO (a, Action, [Output]) | ||
runBuildIO i m = do | ||
(a, BuildW (topologyUpdates, os, liftIOLaters, _)) <- unfold mempty m | ||
runBuildIO !i m = do | ||
(a, BuildW (topologyUpdates, os, liftIOLaters, _)) <- unfold i mempty m | ||
doit liftIOLaters -- execute late IOs | ||
return (a,Action $ Deps.buildDependencies topologyUpdates,os) | ||
where | ||
-- Recursively execute the buildLater calls. | ||
unfold :: BuildW -> BuildIO a -> IO (a, BuildW) | ||
unfold w m = do | ||
(a, BuildW (w1, w2, w3, later)) <- RW.runReaderWriterIOT m i | ||
let w' = w <> BuildW (w1,w2,w3,mempty) | ||
w'' <- case later of | ||
Just m -> snd <$> unfold w' m | ||
Nothing -> return w' | ||
return (a,w'') | ||
{-# inline runBuildIO #-} | ||
|
||
-- Recursively execute the buildLater calls. | ||
unfold :: BuildR -> BuildW -> BuildIO a -> IO (a, BuildW) | ||
unfold !i w m = do | ||
(a, BuildW (w1, w2, w3, later)) <- RW.runReaderWriterIOT m i | ||
let !w' = w <> BuildW (w1,w2,w3,mempty) | ||
w'' <- case later of | ||
Just m -> snd <$> unfold i w' m | ||
Nothing -> return w' | ||
return (a,w'') | ||
Comment on lines
+139
to
+147
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't necessarily need to make |
||
|
||
buildLater :: Build () -> Build () | ||
buildLater x = RW.tell $ BuildW (mempty, mempty, mempty, Just x) | ||
|
@@ -211,6 +213,7 @@ runEvalP :: Lazy.Vault -> EvalP a -> Build (a, EvalPW) | |
runEvalP s1 m = RW.readerWriterIOT $ \r2 -> do | ||
(a,_,(w1,w2)) <- RWS.runRWSIOT m r2 s1 | ||
return ((a,w1), w2) | ||
{-# inline runEvalP #-} | ||
|
||
liftBuildP :: Build a -> EvalP a | ||
liftBuildP m = RWS.rwsT $ \r2 s -> do | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,7 @@ import Reactive.Banana.Prim.Util | |
-- | A 'Network' represents the state of a pulse/latch network, | ||
data Network = Network | ||
{ nTime :: !Time -- Current time. | ||
, nOutputs :: !(OrderedBag Output) -- Remember outputs to prevent garbage collection. | ||
, nOutputs :: {-# unpack #-} !(OrderedBag Output) -- Remember outputs to prevent garbage collection. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoids actually allocating an |
||
, nAlwaysP :: !(Maybe (Pulse ())) -- Pulse that always fires. | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This actually just incurs more boxing than using CPS'ed
WriterT
, because whenever we callrun
we need to box up anIORef