-
-
Notifications
You must be signed in to change notification settings - Fork 369
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
Rewrite hls-graph to not use the Shake code #1759
Conversation
Sorry if it is not related at all but would be #796 relevant? this could enable the change suggested there? |
The work already merged enables #796. This would be going in a different direction with our own implementation |
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.
Very impressive! I read through the code and was able to understand most of it. Planning to play with it this weekend and make it work with the benchmarks.
-- Hold the lock while mutating Ids/Values | ||
databaseLock :: !Lock, | ||
databaseIds :: !(IORef (Intern Key)), | ||
databaseValues :: !(Ids (Key, Status)) |
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.
-- Hold the lock while mutating Ids/Values | |
databaseLock :: !Lock, | |
databaseIds :: !(IORef (Intern Key)), | |
databaseValues :: !(Ids (Key, Status)) | |
-- TODO (someday) Replace the 3 fields below by a concurrent (mutable) Hashtable | |
-- Hold the lock while mutating Ids/Values | |
databaseLock :: !Lock, | |
databaseIds :: !(IORef (Intern Key)), | |
databaseValues :: !(Ids (Key, Status)) |
databaseExtra :: Dynamic, | ||
databaseRules :: TheRules, |
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.
are these fields lazy on purpose?
= Clean Result | ||
| Dirty (Maybe Result) | ||
| Running (IO Result) (Maybe Result) |
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.
= Clean Result | |
| Dirty (Maybe Result) | |
| Running (IO Result) (Maybe Result) | |
= Clean !Result | |
| Dirty !(Maybe Result) | |
| Running !(IO Result) !(Maybe Result) |
resultBuilt :: !Step, | ||
resultChanged :: !Step, | ||
resultDeps :: !(Maybe [Id]), -- Nothing = alwaysRerun | ||
resultData :: BS.ByteString |
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.
resultData :: BS.ByteString | |
resultData :: !BS.ByteString |
let act2 = Box <$> act | ||
let res = unsafePerformIO act2 | ||
(void $ evaluate res, fromBox res) |
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.
I'm not familiar with this trick. What is the Box
for?
-- Catch only catches exceptions that were caused by this code, not those that | ||
-- are a result of program termination | ||
f e | isAsyncException e = Nothing | ||
| otherwise = fromException e | ||
|
||
actionBracket :: IO a -> (a -> IO b) -> (a -> Action c) -> Action c |
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.
actionBracket :: IO a -> (a -> IO b) -> (a -> Action c) -> Action c | |
-- TODO Generalize type signatures and implement exception classes | |
actionBracket :: IO a -> (a -> IO b) -> (a -> Action c) -> Action c |
pure $ ShakeDatabase threads (length actions) actions db | ||
|
||
shakeRunDatabase :: ShakeDatabase -> [Action a] -> IO ([a], [IO ()]) | ||
shakeRunDatabase (ShakeDatabase threads lenAs1 as1 db) as2 = withNumCapabilities threads $ do |
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.
shakeRunDatabase (ShakeDatabase threads lenAs1 as1 db) as2 = withNumCapabilities threads $ do | |
-- TODO move capability bits out of hls-graph | |
shakeRunDatabase (ShakeDatabase threads lenAs1 as1 db) as2 = withNumCapabilities threads $ do |
|
||
data SAction = SAction { | ||
actionDatabase :: !Database, | ||
actionDeps :: !(IORef (Maybe [Id])) -- Nothing means always rerun |
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.
actionDeps :: !(IORef (Maybe [Id])) -- Nothing means always rerun | |
actionDeps :: !(IORef (Maybe [Id])) -- ^ Nothing means always rerun |
After rebasing on top of #1754 benchmarks are failing with out of range errors:
|
That's a different error to what I was seeing. I'll double check tomorrow morning that I didn't forget to send up any of my changes. |
aae24c8
to
4e07089
Compare
act <- uninterruptibleMask $ \restore -> do | ||
-- the child actions should always be spawned unmasked | ||
-- or they can't be killed | ||
async <- async $ restore $ check db key id s |
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.
On IRC, we were discussing if it was possible to make all the book-keeping contention free, by eliminating the locks and running in STM (and using a concurrent map like stm-containers?).
This bit seems to be the problematic part, the rest of the computation seem like it can easily be moved into STM. But it might just be possible to make something work using judicious use of unsafePerformIO
, unsafeIOToSTM
and the proper care. Do you think this would be possible?
Continued in #2060 |
This PR reimplements the key algorithms from Shake directly. Most of the tests still work, but there are some failures relating to progress messages. Unfortunately, those failures also stop the benchmark from working, and thus I have no idea of the relative performance. In order to simplify relative to Shake, and make it more suitable for HLS:
All the interesting code is in the Database module. Everything else is just wrapping and implementing required type classes on the underlying types.
Things that don't work:
How we move forward is probably heavily influenced by what the benchmarks say. If this new Shake is either within the ballpark of same speed or faster, I suggest we move entirely to this new one, at which point things like @pepeiborra's reverse dependencies are way easier to integrate.