-
Notifications
You must be signed in to change notification settings - Fork 323
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
Fix inline compilation benchmarks and Improve searching Graph.Link performance #9520
Conversation
As benchmarks show, a significant amount of time is spent traversing `Set` of `Graph.Link`s. That's unfortunate and unnecessary. We can equally keep helper maps that make search constant time.
var rootScope: Graph.Scope = new Graph.Scope() | ||
private var links: Set[Graph.Link] = Set() | ||
private var sourceLinks: Map[Graph.Id, Set[Graph.Link]] = new HashMap() | ||
private var targetLinks: Map[Graph.Id, Set[Graph.Link]] = new HashMap() |
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.
There is an implementation of serialization logic for the Graph
enso/engine/runtime-compiler/src/main/java/org/enso/compiler/pass/analyse/PassPersistance.java
Lines 153 to 157 in 6665c22
@org.openide.util.lookup.ServiceProvider(service = Persistance.class) | |
public static final class PersistAliasAnalysisGraph extends Persistance<Graph> { | |
public PersistAliasAnalysisGraph() { | |
super(Graph.class, false, 1268); | |
} |
Please make sure that it works correctly with the newly added fields and probably update the serialization id
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.
Should work correctly as I'm reproducing sourceLinks
and targetLinks
from links
when deserialized. I'm not serializing those fields as there is no need for that (links
continues to be serialized).
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.
Glad to see a speedup. Some comments related to the code left inline.
var rootScope: Graph.Scope = new Graph.Scope() | ||
var links: Set[Graph.Link] = Set() | ||
var nextIdCounter = 0 | ||
var rootScope: Graph.Scope = new Graph.Scope() |
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.
If initXyz
is better pattern than calling g.rootScope_$eq(rootScope);
- then rootScope
could be made private as well, possibly.
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 tried and looks like a lot more stuff depends on it being public. I tried to keep the PR succinct for now.
engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/alias/Graph.scala
Show resolved
Hide resolved
engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/alias/Graph.scala
Outdated
Show resolved
Hide resolved
engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/alias/Graph.scala
Outdated
Show resolved
Hide resolved
@@ -129,7 +155,10 @@ sealed class Graph extends Serializable { | |||
* @return a list of links in which `id` occurs | |||
*/ | |||
def linksFor(id: Graph.Id): Set[Graph.Link] = { | |||
links.filter(l => l.source == id || l.target == id) | |||
sourceLinks.getOrElse(id, Set.empty[Graph.Link]) ++ targetLinks.getOrElse( |
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.
Great finding. Good fix. Thank you.
engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/alias/Graph.scala
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
def getLinks(): Set[Graph.Link] = links |
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.
Wouldn't it be better to remove the links
field all together and just compute the links from sourceLinks
and targetLinks
? The logic between initLinks
and getLinks
& co. would be simpler and possibly getLinks()
isn't on critical path. Otherwise the inconsistency must have been caught somewhere, right?
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 kind of like that links
is the source of truth and sourceLinks/targetLinks
serve as aux indexes for quicker access. It also simplifies serde.
Treat InlineContext as a closeable resource, to ensure that benchmarks properly cleanup. The problem was that the number of scopes has been steadily increasing with every benchmark run. Traversing such additional scopes took time, hence exponential blow up in run times.
With the last change the inline compilation benchmarks are back in order:
|
Pull Request Description
As benchmarks show, a significant amount of time is spent traversing
Set
ofGraph.Link
s. That's unfortunate and unnecessary. We can equally keep helper maps that make search constant time.Fixed inline compilation benchmarks by properly cleaning up scopes after runs.
Closes #9237.
Important Notes
Things like
are all gone. There is plenty of it those are just samples.
Benchmarks are back in order:
Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,
and
Rust
style guides. In case you are using a language not listed above, follow the Rust style guide.