-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Cache ConformanceAccessPaths in GSB::EquivalenceClass for big wins #18597
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
This dramatically speeds up SubstitutionMap::lookupConformance, shaving off 1/3 of the time spent compiling the standard library.
@swift-ci Please test compiler performance |
@swift-ci Please test |
lib/AST/GenericSignature.cpp
Outdated
@@ -976,6 +981,7 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath( | |||
// Add the root of the path, which starts at this explicit requirement. | |||
path.path.push_back({rootType, conformingProto}); | |||
}; | |||
buildPath = buildPathLambda; |
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 don't understand the purpose of binding buildPath
specifically as a function_ref
here.
Oh, I guess it uses itself recursively? Well, function_ref
is better than std::function
, at least.
...should this just be hoisted to file scope? This function is huge, and it mostly relies on its parameters, not captures.
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.
That would probably work too. I didn't want to modify code I didn't understand too much, but the allocation was bothering me.
lib/AST/GenericSignature.cpp
Outdated
@@ -985,6 +991,7 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath( | |||
buildPath(getRequirements(), source, protocol, rootType, nullptr); | |||
|
|||
// Return the path; we're done! | |||
equivClass->conformanceAccessPathCache[protocol] = path; |
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 we're caching these instead of building them on-demand, can we reasonably return them by reference? Or make ConformanceAccessPath
just hold a reference to external storage so that it's cheaper to pass one around?
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.
That seems sensible too.
That looks pretty nice. :) |
So much so that I'm suspicious! How did it end up outputting less LLVM? |
One possible reason is - some of the projects failed while compiling with changes vs. without, is that right, @graydon? |
It's supposed to ignore that, because if it didn't you'd get no useful data at all if one project fails. But that's my best guess too… |
John pointed out that if we're going to cache them, we might as well go all the way and pass them around by reference.
It's a recursive helper that only captures one argument other than 'this'. Pay the cost of putting a declaration in a commonly-included header to simplify the code. No intended functionality change.
@swift-ci Please smoke test |
That looks great, thanks! |
@swift-ci Please smoke test Linux |
@xedin @jrose-apple I don't know how this is happening (it is indeed supposed to be ignoring cases that failed when computing deltas!) but those stats are definitely indicative of a measurement error. If you look at the detailed-stats deltas, it's counting the intake of 43% less source-lines of code (AST.NumSourceLines); everything else follows from that. |
(Slightly more-nuanced read: the patch breaks non-WMO builds of a few projects. The actual improvement is seen in the release detailed counters -- Sema.NumGenericSignatureBuilders decreases by 7.5% -- with no improvement to time or space enough to register above threshold in the brief summary) |
@swift-ci Please test source compatibility |
Yep, looks like segfaults while building some things. Hm. |
All right, let's try this again: @swift-ci Please test compiler performance |
!!! Couldn't read commit file !!! |
@swift-ci Please test compiler performance |
There are still more projects failing to build in Debug mode. I'm looking into that today. |
Build comment file:Summary for master fullUnexpected test results, excluded stats for RxSwift, ChattoAdditions, ProcedureKitCloud, DatabaseKit, ReactiveSwift, ReactiveCocoa, Wordy No regressions above thresholds Debug-batchdebug-batch briefRegressed (0)
Improved (3)
Unchanged (delta < 1.0% or delta < 100.0ms) (0)
debug-batch detailedRegressed (0)
Improved (70)
Unchanged (delta < 1.0% or delta < 100.0ms) (18)
Releaserelease briefRegressed (0)
Improved (0)
Unchanged (delta < 1.0% or delta < 100.0ms) (3)
release detailedRegressed (0)
Improved (1)
Unchanged (delta < 1.0% or delta < 100.0ms) (22)
|
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 looks great. I had this on a TODO list somewhere as a lower-priority optimization but never imagined it would be such a win. Thank you!
Okay, a few more of those Debug projects should pass now, but still not all of them, so I'm just going to merge this. |
This dramatically speeds up SubstitutionMap::lookupConformance, shaving off 1/3 of the time spent
compiling the standard librarygenerating the standard library module.