You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As developers are gradually migrating to modern, post-.NET 5 WinRT interop, more and more projects are relying on CsWinRT to provide the interop infrastructure for WinRT. Part of CsWinRT's architecture requires source generators and a considerable amount of analysis and code generation in order to make code trim-safe and AOT-safe. As we keep improving on things (and especially with the work planned for CsWinRT 3.0, which will require even more supporting code generation than 2.x currently does), the performance of our source generators is increasingly becoming a concern, and we're exploring ways to improve things.
We've had multiple reports of Visual Studio having poor performance because of CsWinRT's generators, and we could reproduce the issue ourselves (it's a well known performance issue that we've talked about to various Roslyn folks before, like @CyrusNajmabadi and @sharwell). This is affecting both internal partners (eg. folks in the Microsoft Store team and other inbox apps, as well as all the engineers starting to use C# for Windows components), and developers in the community, who have frequently pinged us asking for solutions to this problem.
A key aspect of this is: our generators are inherently expensive, as we must analyze almost all syntax nodes in each project.
Another one is: virtually all the codegen from CsWinRT is implementation only.
We only generate things which have no impact on IntelliSense. Yet, despite us already using RegisterImplementationSourceOutput, our generator is run way more than it should, especially when loading a solution (with multiple people reporting Visual Studio and the Roslyn process consuming a huge amount of RAM and CPU for minutes while opening a solution containing projects using CsWinRT). Our generators are
It's been suggested to rewrite our generators as an MSBuild task. However, that doesn't seem scalable, would introduce a lot of additional complexity on our end, introduce more chances for things to not work correctly, and we'd also have to manually figure out some way to still wire up all the same Roslyn infrastructure from our build task anyway, because we still need to have access to all the Roslyn type system to do our analysis.
We'd like to have a way to configure a source generator to effectively be just like a build task: build only, nothing else.
We're already using RegisterImplementationSourceOutput, but our understanding is that, despite its name, this API is not actually doing what you'd expect it to do at all. Instead, it's functionally identical to RegisterSourceOutput, which we don't want (as that runs way too often). For our needs, it'd be sufficient for RegisterImplementationSourceOutput to be updated to only ever run for actual builds:
Not when the project is loaded
Not when typing
Not when saving a file, etc.
Literally only doing a real build, like a build task wired up to eg. BeforeTargets="CoreCompile" would (example).
Alternative solutions
Some other way (eg. attribute?) for generators to explicitly indicate "treat me like a build-only task". This however would require a new API, and it seems like from the API name, RegisterImplementationSourceOutput should already be expected to have this semantics anyway.
My take on this is simply: if it this expensive, just write a tool that is explicitly invoked to do the analysis and emit the desired code.
to be updated to only ever run for actual builds:
Not when the project is loaded
Not when typing
Not when saving a file, etc.
Literally only doing a real build, like a build task wired up to eg. BeforeTargets="CoreCompile" would (example).
If you are literally only doing a real build... the why not make a build tool/task?
Related to dotnet/runtime#114179: .NET and Native AOT improvements for CsWinRT 3.0
Background
As developers are gradually migrating to modern, post-.NET 5 WinRT interop, more and more projects are relying on CsWinRT to provide the interop infrastructure for WinRT. Part of CsWinRT's architecture requires source generators and a considerable amount of analysis and code generation in order to make code trim-safe and AOT-safe. As we keep improving on things (and especially with the work planned for CsWinRT 3.0, which will require even more supporting code generation than 2.x currently does), the performance of our source generators is increasingly becoming a concern, and we're exploring ways to improve things.
We've had multiple reports of Visual Studio having poor performance because of CsWinRT's generators, and we could reproduce the issue ourselves (it's a well known performance issue that we've talked about to various Roslyn folks before, like @CyrusNajmabadi and @sharwell). This is affecting both internal partners (eg. folks in the Microsoft Store team and other inbox apps, as well as all the engineers starting to use C# for Windows components), and developers in the community, who have frequently pinged us asking for solutions to this problem.
A key aspect of this is: our generators are inherently expensive, as we must analyze almost all syntax nodes in each project.
Another one is: virtually all the codegen from CsWinRT is implementation only.
We only generate things which have no impact on IntelliSense. Yet, despite us already using
RegisterImplementationSourceOutput
, our generator is run way more than it should, especially when loading a solution (with multiple people reporting Visual Studio and the Roslyn process consuming a huge amount of RAM and CPU for minutes while opening a solution containing projects using CsWinRT). Our generators areIt's been suggested to rewrite our generators as an MSBuild task. However, that doesn't seem scalable, would introduce a lot of additional complexity on our end, introduce more chances for things to not work correctly, and we'd also have to manually figure out some way to still wire up all the same Roslyn infrastructure from our build task anyway, because we still need to have access to all the Roslyn type system to do our analysis.
We'd like to have a way to configure a source generator to effectively be just like a build task: build only, nothing else.
cc. @jaredpar @chsienki
Proposed solution
We're already using
RegisterImplementationSourceOutput
, but our understanding is that, despite its name, this API is not actually doing what you'd expect it to do at all. Instead, it's functionally identical toRegisterSourceOutput
, which we don't want (as that runs way too often). For our needs, it'd be sufficient forRegisterImplementationSourceOutput
to be updated to only ever run for actual builds:Literally only doing a real build, like a build task wired up to eg.
BeforeTargets="CoreCompile"
would (example).Alternative solutions
RegisterImplementationSourceOutput
should already be expected to have this semantics anyway.Related items
RegisterImplementationSourceOutput
-based incremental generators on every keystore #77288The text was updated successfully, but these errors were encountered: