Skip to content

Fix asymptotic performance issues in live variables analysis. #82

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

Merged
merged 1 commit into from
Jul 18, 2014

Conversation

retronym
Copy link
Member

Fix possibly-exponential runtime for DFS graph searches.
Improve DFA fixpoint algorithm to correctly compute worklist
of only changed nodes for each iteration.

Added test that takes > 2 minutes to compile without these
improvements.

Fix possibly-exponential runtime for DFS graph searches.
Improve DFA fixpoint algorithm to correctly compute worklist
of only changed nodes for each iteration.

Added test that takes > 2 minutes to compile without these
improvements.
@retronym
Copy link
Member Author

Based on #78. I've reformatted the commit message and retargetted the PR to 2.10.x

@retronym
Copy link
Member Author

LGTM. @gnovark Can you please sign the Scala CLA?

@retronym retronym added this to the 0.9.2 milestone Jul 15, 2014
@retronym retronym self-assigned this Jul 15, 2014
@retronym
Copy link
Member Author

For the record, the this PR is a lot easier to review with a side-by-side diff, as provided by IOctosplit

val preds = asyncStates.filter(_.nextStates.contains(at.state)).toSet
preds.flatMap(p => lastUsagesOf(field, p, avoid + at))
def lastUsagesOf(field: Tree, at: AsyncState): Set[Int] = {
val avoid = scala.collection.mutable.HashSet[AsyncState]()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems this optimization (turning the avoid parameter into a local variable, which is a mutable hash set) is independent of the rest of this change set. If so, what's the performance improvement? The code is slightly longer and more imperative, so we might want to have a good reason to do it. What do people think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My interpretation of this code is that it's a standard depth-first search through the state graph, just like isPred. If I recall correctly, without this change there is measurably exponential runtime growth when adding an extra level of nesting in the example, which would occur if the state graph has repeatedly-chained 'diamonds', e.g.

1->2
1->3
2->4
3->4

and so forth.

The immutable version doesn't remember that it's traversed the entire subgraph starting from 4, so ends up exploring the exponential number of paths from 1 to the final state.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That clarifies it- thanks! So, yes, this optimization is definitely essential.

@phaller
Copy link
Contributor

phaller commented Jul 18, 2014

LGTM

phaller added a commit that referenced this pull request Jul 18, 2014
Fix asymptotic performance issues in live variables analysis.
@phaller phaller merged commit 75ef24d into scala:2.10.x Jul 18, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants