Our great sponsors
-
It would be interesting to bench something extremely lightweight (like https://github.com/edubart/minicoro) against these runtimes.
By my back-of-the-napkin math, 1,000,000 coroutines would cost about 64mb + 2mb/core for stacks.. which works out to about 4x less memory than the 'winner' of this comparison, and ~30x less than go.
-
AspNetCoreDiagnosticScenarios
This repository has examples of broken patterns in ASP.NET Core applications
To expand upon this thought, here is the AsyncGuidance doc[1] on why not to use .Result to get the return value of a completed Task in C#.
To make this simple they introduced async Main[2] a few years ago.
[1]: https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/b...
-
WorkOS
The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.
-
-
"System time" rather than "user time" is the majority (7.94s system time, 2.83s user time in the 20.25s wall time run). Is this pointing to memory allocations?
Crystal Fiber docs https://crystal-lang.org/api/1.8.2/Fiber.html says "A Fiber has a stack size of 8 MiB which is usually also assigned to an operating system thread. But only 4KiB are actually allocated at first so the memory footprint is very small." -- and perhaps unsurprisingly, 4KiB times 1000000 is approximately 4 GiB. Nice when the math works out like that :)
To me this is useful as a baseline for something like a websocket server, with some number of idle connections, each Websocket connection mapped to a Fiber that is waiting for I/O activity but mostly idle.
-
Pfft doubtful. Rust, C and C++ all have very similar performance. And apparently a javascript framework is currently beating all of those languages in the composite score on techempower, though that seems a bit weird to me:
https://www.techempower.com/benchmarks/#section=data-r21&tes...
C doesn't have a built in, optimized async execution engine of any sort. C with threads would lose to any of the async runtimes here (including javascript).
C++ has async now. By all means, write up an async C++ example and compare it. I suspect a good C++ async executor would perform about as well as tokio, but it'd be nice to know for sure.
I'd also be interested to see how hard it is to write that C++ code. One nice thing about Rust and Go is that they perform very well with naively written code. (Ie, the sort of thing chatgpt, or most of your coworkers would write.) Naive C would use kernel threads, so if we're comparing average C code to average Go code at this test, the average go code will end up faster.
(This isn't always true of rust. I've seen plenty of rust code which uses Box everywhere that runs crazy slow as a result.)
-
I was sufficiently curious and just went and tested this using BenchmarkDotNet. The example code is here (https://github.com/J-Bax/CSharpBenchmarkExamples).
The difference is quite significant.
(1) With the authors code (using Task.Run), I get ~428MB of allocations.
(2) Dropping the unnecessary Task.Run(...), I get ~183MB of allocations.
(3) Doing (2) and waiting N times on the same delay, I get ~39MB of allocations.
This was all using .NET 6 too. .NET 7 or the 8 preview might be even better since they are working hard on performance in recent releases.
So even looking at just (2), that puts .NET on par with the rust library.