-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Proposal: provide trigger info to generators to enable more expensive workloads #51497
Comments
For reference, we at Silk.NET would also benefit a lot from this. |
@chsienki @jasonmalinowski relevant to the discussions around Step based APIs |
@chsienki Given all we've done for incremental APIs and then also the proposed API for implementation-only stuff, do we have anything more for this? |
I would consider this issue resolved now. Incremental generators have addressed the issues surrounding performance hits with expensive generation, and further performance improvements for build-time specific steps are already possible with |
Overview
Let me start by saying that source generators are absolutely brilliant, they're super powerful and a lot of fun to use 🎉
This proposal is a follow up from a conversation in the C# Discord in
#roslyn
(as suggested by @CyrusNajmabadi) and it's about giving more info to source generators so that they can better organize their workflow, and in particular opt-in into more expensive code paths that could not be sustainable if the generator is just being invoked multiple times a second. This would be extremely useful in more advanced scenarios. Here's a complete breakthrough of the problem this would solve, and the proposed solution.The problem
Source generators are by default being invoked multiple times a second by Roslyn, which makes their overhead pile up pretty fast especially when there's multiple generators in use in the project being worked on. Because of this, quoting Cyrus, they should "try to take 1ms or less". Which is absolutely fine in many common scenarios such as:
In general, when the generator is doing some reasonable work within the tight constraints of the official guidelines and just generating some code, things are absolutely fine. But, what if a generator needs to do some more expensive work, say anything that takes >= 100ms? Right now that's simply not doable, because it would immediately cripple the entire IDE.
There is a big consideration here: not all work has to be done at every keystroke or cursor movement. Especially for more expensive work, it would often be absolutely fine to just have the generator run only before the project is actually being built (either from VS or from
dotnet build
, just in all cases where an assembly is being built). In these cases, a generator taking longer to do work would be perfectly acceptable as the UX wouldn't suffer much. After all, developers would have had to stop for a bit anyway to wait for the build to be finished before doing more work.Yes, one could setup an MSBuild pre-build task to achieve something like this. But that has lots of downsides:
The proposed solution
We could solve this with minimal changes to the public API surface by adding something like this to
GeneratorExecutionContext
(possibly toGeneratorInitializationContext
too, thought that may be not necessary):This single change would make source generators much more flexible and allow developers to:
ExecutionTrigger
and return immediately.One practical example: ComputeSharp
I've talked with a few developers in the C# Discord server about this and many have expressed interest for such a feature, as it would give them more freedom to do expensive operations in a generator that are not "dynamic", as in, they don't need to be run all the time, but just need to be executed "at least once" before the project is built. That is something that currently just cannot be expressed in a source generator, and that this proposal would solve.
To add to that, I want to make a practical example to show where/how this proposal could be useful. I have a project called ComputeSharp, which is a library that allows C# developers to execute code on the GPU. They simply write a compute shader in C#, and then the library transforms their code to HLSL, dynamically compiles a DX12 compute shader and runs it on the GPU. The general workflow is as follows:
struct
type with anIComputeShader
interface), in C#.IComputeShaderSourceGenerator
generator kicks in, performs C# -> HLSL transpilation (I'm sorry @333fred, I know 🤣), and generates some methods to invoke each shader type appropriately (they're defined here).This approach works great, but there's some obvious downsides:
With the proposed solution, my
IComputeShaderSourceGenerator
generator could just do this:Hope this helps! 🙂
The text was updated successfully, but these errors were encountered: