-
Notifications
You must be signed in to change notification settings - Fork 571
Fix exponential collapsing of BindingGroups #4006
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
Conversation
|
Great work! This looks sensible to me. Does this new test fail without this fix, at least on machines where you don’t have an enormous amount of memory? |
|
I tested it on my PC and it failed on |
hdgarrood
left a comment
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.
Nice, thanks again
rhendric
left a comment
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.
Nice work!
|
The new test takes ~3 minutes to compile on my machine. This isn’t noticeable with the absurdly long build times we get with Travis these days but this will be more noticeable when we’ll switch to GitHub actions. Is that ok or should we try to exhibit a test case that compiles faster? |
I think it would be preferable, least of all because this makes running tests in development quite an ordeal. I wouldn't care as much if this was only run in CI (or with a CLI flag). |
|
I suppose since this was exponential before, the smallest program that's big enough to be likely to cause an OOM could potentially be a fair bit smaller than this test. |
|
Okay, I have shrinked the test case to just two "repetitions" as it still breaks the build on my PC on master and passes within 16 seconds on my branch. Is that acceptable? |
|
I think 16 seconds is a bit of a drag, but just about manageable. Ideally we'd have a slightly more sophisticated mechanism for detecting performance regressions than just writing test cases that are likely to fail with OOM errors if things regress, but that's a whole project in of itself. Any objections to merging this as-is? |
Description of the change
In short:
When you dfs through a tree and launch the same dfs on each node then you go exponential.
In long:
I have spotted that function definitions which are big enough (see the added testcase) tend to blow up the memory and take extreme amount of time to handle.
The issue was triggered particularly in the
collapseBindingGroupsas it was running a traversal through the whole AST of each declaration that on everyletwas calling thecollapseBindingGroupswhich was running a traversal through the whole AST of each declaration that on everyletwas calling thecollapseBindingGroupswhich was running a traversal through the whole AST of each declaration that on everyletwas calling thecollapseBindingGroupswhich was running a traversal(...)More clearly,
collapseBindingGroupsused to runcollapseBindingGroupsForValueon each AST node which was runningcollapseBindingGroupson everyletexpression. This was effectively forcing all innerlets to be visited twice which, by the fact, that each of these duplicated evaluations was running next two ones, was amplifying the problem leading to exponential complexity over the depth of a tree.Since the purpose of this function is to flatten the binding groups of the declarations across the whole AST, I changed the folding function for
everywhereOnValuesto simply flatten a single layer of declarations. It works perfectly as going deeper is already handled byeverywhereOnValues.I have prepared a testcase that fails on the
masterbranch but is successfully solved after the fixes.Work on this PR was funded by aeternity