-
Notifications
You must be signed in to change notification settings - Fork 127
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
Constant propagation directly from MarkStep #1771
Conversation
Add a test for the complex case
Don't store methods on stack in the same structure as methods which are already processed. Makes the processed methods structure more strongly typed.
void ProcessMethods (Collection<TypeDefinition> types) | ||
{ | ||
foreach (var type in types) { | ||
if (type.IsInterface) |
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.
Looks like we no longer check for interfaces - does it just mean that default interface methods can have branches removed?
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.
Good catch - and basically yes. I fixed it (unintentionally 😉 ). So I now added at least a basic test that branch removal works within default interface methods.
Add a test for branch removal in default interface methods
Includes fixes to improve linking performance dotnet/linker#1771
Call constant propagation and branch removal processing directly from `MarkStep`: * Renames `RemoveUnreachableBlocksStep` to `UnreachableBlocksOptimizer` - it's not a step anymore * Rename members to use the `_name` naming convention (which is also used by `MarkStep`) * Removes the "go over all methods in all assemblies and process them" logic * Some small changes to the `ProcessMethod` API to be more suitable for the `MarkStep` * The class is now instantiated by `MarkStep` and only lives as long as `MarkStep` does * `MarkStep.ProcessMethod` calls the optimizer's `ProcessMethod` before doing anything else on the method (this is because the optimizer can modify methods body, so mark step should only look at the modified version of the method) Some interesting statistics (on console helloworld): * Before this change the optimizer processed 73K methods (every method at least once - total number of methods is 72K). After the change the optimizer only processes 12K methods (so a huge reduction). This also means that the large dictionary maintained by the optimizer on all processed methods is now 20% of before this change. * Max stack size increased to 62 - this is because of different order of processing methods. The 62 comes from `ThrowHelpers` which initializes lot of resource strings (each a separate call to a different method), so at one point all of these dependencies are on the stack. This is not a problem, just slightly higher memory usage. It would become problematic if the stack depth reached several 1000s which is VERY unlikely to happen. * Number of rewritten methods is down to 20% (from 746 to 117) - all of those not rewritten are actually not used by the app * As far as I can tell, it produces the exact same output. Very rough perf measurement on Blazor template app: * Before all the constant prop changes (SDK from early December 2020): 6.1 seconds (on average) * After this change: 3.4 seconds (on average) Commit migrated from dotnet/linker@d8c44b8
Call constant propagation and branch removal processing directly from
MarkStep
:RemoveUnreachableBlocksStep
toUnreachableBlocksOptimizer
- it's not a step anymore_name
naming convention (which is also used byMarkStep
)ProcessMethod
API to be more suitable for theMarkStep
MarkStep
and only lives as long asMarkStep
doesMarkStep.ProcessMethod
calls the optimizer'sProcessMethod
before doing anything else on the method (this is because the optimizer can modify methods body, so mark step should only look at the modified version of the method)Some interesting statistics (on console helloworld):
ThrowHelpers
which initializes lot of resource strings (each a separate call to a different method), so at one point all of these dependencies are on the stack. This is not a problem, just slightly higher memory usage. It would become problematic if the stack depth reached several 1000s which is VERY unlikely to happen.Very rough perf measurement on Blazor template app:
Part of #1733