Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't know if this proposal makes a lot of sense.

The existing async1/TPL path is stable & predictable. If you find yourself needing more performance, you can reach for hardware Thread instances and use whatever locking/waiting/sharing/context strategies you desire. Anything else is a weird blend of compromises that is going to have caveats that are not immediately obvious for your specific use case.

For example, async2 w/ runtime JIT appears to have some tradeoffs with regard to GC & memory usage and the experiment writeup leaves some open-ended questions here[0].

[0]: https://github.com/dotnet/runtimelab/blob/feature/async2-exp...



> If you find yourself needing more performance, you can reach for hardware Thread instances

True for code your team write, but async/await is kind of viral, and many libraries now only have async APIs, which makes them difficult to shoehorn into a threading approach.


> async/await is kind of viral

Exactly part of my concern. Hypothetically we've got 2 competing viruses now.


Surely it's the same "virus"? Unless I'm mistaken, the async2 proposal wouldn't require any code changes, as it essentialy just moves compiler stuff to the runtime.


They still need to interop the old async with the new async, without requiring recompilation of everything, otherwise it is going to be another .NET Framework to .NET Core, which is still ongoing.


The current generated state-machine mechanism is not going away any time soon. Instead, Roslyn as well as any other compiler that targets CIL is expected, when appropriate, to stop generating state machines and start generating specially annotated method calls recognized by .NET.

This means that all existing libraries will continue working as is, and newly written or existing code that is compiled against e.g. C# 14/.NET 10(?) can automatically opt into new mechanism without user intervention. The write-up does cover the considerations for interoperability between these two models as well.

In fact, this will make using async from other CIL-based languages much easier as the burden of capturing the state and suspending/resuming the execution will be on the runtime rather than language compiler authors.


The kind of scenarios where this kind of interop is put to test is when old code, without being recompiled, takes a subclass, an interface implementation, a member reference, a delegate, or a lambda, compiled with async2 model, as parameter, and everything works as expected.

Something that I hope they take into account, having new code calling into the old code, is the easy part of the problem.


Yes, we considered that and implemented a solution. Effectively, the runtime will generate thunk methods that will invisibly bridge between the two worlds. Calling (and overriding) regular async methods with runtime async methods will be stitched up by the runtime. The user will never see the difference.


Cool! Thanks for jumping in.


In practice we don't think there will end up being tradeoffs in async2 vs. async1. If you look below, at the "JIT state machine" section, you'll see that async2 looked better and the GC behavior differences were probably transient.

Overall, there are no architectural reasons why the compiler version should be better. The runtime should be able to make perf decisions that are at least as good in every case.


Trying to do clever stuff with threads tends to lead from brow beating, wailing, and gnashing of teeth by various folks who insist to just trust the threadpool.




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: