C# now beats Rust on WASM size

105 pointsposted 10 hours ago
by sumnole

45 Comments

sondr3

5 hours ago

It's a bit of an unfair comparison, the benchmarked C# code here is also post-processed which none of the other targets are. See this comment[1] on reddit where the author announced this on the /r/dotnet subreddit, Rust can go much, much lower. The title is misleading at best and a lie at worst, this is great but saying it beats Rust is a far cry from the truth except for the very narrow benchmark made to showcase this tool.

[1]: https://www.reddit.com/r/dotnet/comments/1x7wsgb/rust_just_l...

torginus

3 hours ago

This is an entirely different toolchain from the official .NET one, which is kind of the point of the post. It is experimental, but intended to for production, not for beating benchmarks.

Rust also builds a pretty small binary, which is cool. This isn't really meant to be a 'C# is better than Rust' post, but more pointing out that Blazor (which is the official MS implementation) builds huge binaries; often >10MB, which is a real problem. This fixes that.

xxs

5 hours ago

personally, I disregard and ignore cross-language benchmarks. Benchmarks are hard, benchmarks in managed languages are extra hard.

And then the person writing the code has to be an expert in all languages involved to make it even half fair, instead of just a sound-bite/click-bait.

galangalalgol

27 minutes ago

I think the benchmark game was really useful. It wasn't a which is better, it was what are the tradeoffs. Some of that was provided subjectively by curating it into safe and portable vs hyperoptimized categories. But there is also memory footprint etc. It was also a gauge of which languages people who care about performance preferred, as those got rapid updates.

CharlieDigital

3 hours ago

There's something about C# that just feels so right for me for backends (as long as you stick to the more modern conventions).

Good tooling, modern language features (C# 15 has the long awaited unions, closed hierarchies), great debugging experience, etc.

mhh__

an hour ago

Yes I think it's a bit underrated. The problem I find is that no one writes C# libraries that actually do anything (e.g. even basic linear algebra is pretty crap compared to python) and that the JIT is a pointless hindrance but the experience of using the stack is pretty good.

xnorswap

9 minutes ago

I agree completely regarding libraries, C# has never had the "libraries for everything", especially open source ones. The better libraries have moved to ( or always have been ) licensed too which doesn't help that impression.

I'd like to hear more about your issue with the JIT and where do you find it a hindrance?

I've had a few benchmarks lately that performed better under JIT than AOT compilation, and while that isn't always the case, the JIT, especially on dotnet 10, performs very well.

benterix

24 minutes ago

> The problem I find is that no one writes C# libraries that actually do anything

Yes, because when you think about it, why should they?

MS has showed many times how unreliable and even user-hostile they can be, so the community at large is very wary of their ecosystem in spite of real advancements.

dude250711

2 hours ago

If all possible metrics are considered, C# might be the best language ever created.

CharlieDigital

2 hours ago

I really like TS as well, but what kills it for me is the fragmented tooling landscape and tendency to bad practices by undisciplined devs (lack of explicit types making things hard to track down). I also hate writing intermediate schemas (zod, valibot, etc.) to get runtime type safety (love Typia for this). Debugger is flaky based on setup as well. I like writing TS solo, but hate doing it in a team environment.

gf000

an hour ago

That's probably the very reason it's arguably not the best language ever created. It has way too large surface area, getting close to C++ levels.

Sure, it's a valid language design, but it's also a negative in "understandability of each line of code", and thus maintainability, and even stuff like tooling, verification.

simonask

2 hours ago

C# is an odd one. It's surprisingly flexible, but then oddly lacking in other areas. Quite productive, but also quite inconsistent and uncomposable.

Once you've tried a better type system (Rust), it's difficult to go back to C#. People jump through all kinds of hoops to get good performance out of it, and they're mostly able to.

Things I dearly miss from Rust when I'm using C#:

- Associated types in interfaces. (IEnumerable should not be forced to return a type-erased = heap allocated IEnumerator instance.)

- Move-only structs. (Currently, every type with value semantics is trivially copyable, even ref structs.)

kfuse

26 minutes ago

"IEnumerable should not be forced to return a type-erased = heap allocated IEnumerator instance."

Foreach loops use compile-time duck typing, so if you don't intend to use your enumerable in LINQ then both the enumerable and enumerator don't need to implement any interfaces.

This optimisation covers only one common use case, but that's the way of things in C# land.

zarlo

12 minutes ago

IEnumerators can also be value types So no heap allocation, just stack.

slightly off topic but a lot of things in .NET actually use compile time duct typing. like how async works To make your own task, you don't add an interface to it. You just implement a single method.

pif

an hour ago

Nice, but still lacking proper generics (i.e. à la C++ templates) and typedef.

whizzter

an hour ago

Different use-cases.

C# is often like Java but without taking a wrong turn when it came to type-erased generics, the generics are uncomplicated enough even if slightly less powerful than what you get with the full instantiation of C++.

C++ was severely lacking before reflection came along in 26, I'm actually writing some new reflection based libraries and it's mostly a joy and quite capable.

But C++ has so many outrightly dangerous semantics when it comes to writing secure code, the coping of pointing to realtime systems,etc as another security "dimension" doesn't hold when Rust,etc exist today.

C# is good in that it's "easy" yet the performance profile of the features allows optimized code to run far closer to C++/rust/etc in performance compared to Java,etc. (that said, a wast majority is probably running like Java due to programmer patterns, but not needing to drop down to another language when it's needed feels good).

TazeTSchnitzel

3 hours ago

> The 46.7 KiB program is the baseline, not the boundary.

what does this even mean

NewsaHackO

2 hours ago

Slightly off topic it is just so bizarre how often Claude uses this turn of phase. It’s almost seems forced here. Anthropic has to be hard coding it to do this.

dionian

3 hours ago

I speak claude, it means 46.7 is the minimum and it could go further.

dude250711

2 hours ago

He was absolutely right to push back though.

Scaled

3 hours ago

Worth pointing out this is not open source, if that is an important consideration when you're comparing the two (it is to me).

zarlo

19 minutes ago

Yeah, I'm not going to use a toolchain where if my project is successful, I'm going to end up having to pay.

weinzierl

6 hours ago

This is s bit of an unfair comparison, isn't it?

Since WASM ships with a garbage collector that C# can use while Rust does all the memory management itself, of course it will be bigger.

EDIT: Reading OP more thoroughly I think I'm wrong. Apparently in the compared versions, the C# version ships a runtime with garbage collector.

afdbcreid

5 hours ago

C# doesn't (and can't) use WASM GC.

The comparison is unfair for other reasons (the C# runtime was optimized for WASM size and the Rust not, it's possible to be much smaller in Rust), but it's still cool.

xnorswap

5 hours ago

Any cross-language benchmarks are always unfair for those kinds of reasons, because ultimately everything is eventually possible against any given hardware.

What matters more for comparing what you get out of languages is the output of idiomatic code written against typical frameworks.

Indeed, it's still cool to see, even if it's optimised to beyond recognition, as seeing the occasional C# win is nice to keep the "re-write in rust" wolves from the door, who seem to ever lurk, especially in a world where re-writes appear easier.

afdbcreid

5 hours ago

> ultimately everything is eventually possible against any given hardware.

Not everything, no. You can't run C# without the .NET runtime. Some parts of it are irreplaceable.

And the Rust optimizations to shrink binary size (see https://github.com/johnthagen/min-sized-rust) are commonly done in production when it matters, not just in WASM but also in embedded.

memsom

4 hours ago

> Not everything, no. You can't run C# without the .NET runtime

You can compile C# to an AOT exe, and when you do that it will literally only be what it needs to work, less and dynamic libs.

jeswin

4 hours ago

> You can't run C# without the .NET runtime

With NativeAOT, same a golang then. NativeAOT has worked wonderfully for us, and in some specific situations faster than Rust.

fweimer

3 hours ago

Is the support gap mostly related to weak references and finalizers? Or is something else missing?

(Obviously those are already pretty significant gaps.)

VimEscapeArtist

40 minutes ago

C# will slowly fade in relevance. Nowadays it gets picked mainly when the company already has a lot of .NET in place.

hvb2

39 minutes ago

Why? What makes you say that? In favor of what?

kcb

35 minutes ago

The models aren't writing new applications in C# unless you direct it to.

dev_l1x_be

3 hours ago

X is better than Y where Y is irrelevant and the difference is marginal is a low relevance observation.

andsoitis

10 hours ago

this looks phenomenal. Can't wait to try it out.

jedisct1

4 hours ago

Not very hard... Rust wasm binaries are ginormous.

If you care about WASM performance, size and memory usage, Zig is a much better candidate.

flohofwoe

an hour ago

Not necessarily true (especially with the new Zig Io interface), a vanilla Rust Hello World compiles to a 40 KBytes WASI blob, while a vanilla Zig Hello World compiles to 45 KBytes. Both are in the same ballpark. The vanilla C Hello World on the other hand comes out at around 4 KBytes (with the caveat that the compiler is free to replace a non-formatting printf with a direct puts call).

WhereIsTheTruth

2 hours ago

Of course, they lobbied to transfer the bloat onto the WASM runtime itself

edave64

24 minutes ago

Maybe I'm ignorant of some fundamental limitation here, but I cannot get excited for 47kB for a `print(42)`.

bob1029

5 hours ago

I never understood the appeal of wasm outside special performance cases. We never once considered moving from Blazor server side to the wasm mode. Not one time in 5+ years did it ever come up. The whole idea turned out to be a huge distracting waste of engineering talent. Instead of chasing this idealistic wasm pipeline and struggling with weird websocket transports, we could have been writing boring old cshtml and JavaScript on top of stateless HTTP.

Unless you are building a web version of autocad or premiere, I don't see the point of engaging with this technology.

pjc50

4 hours ago

> Unless you are building a web version of autocad or premiere,

Yes, but that's the use case. I don't think you'll be able to find someone respected saying "yes we should use this for all use cases regardless of what you're doing". At the other end, htmx is completely fine.

bluegatty

4 hours ago

It's for in-browser, security and portability, generally not worth it performance.

A lot of edge cases they'd rather run WASM then a JS or Python VM, it has nicer containerization characteristics. But even with those key cases - it's not necessarily a core, critical technology.

WASM is 'always on the horizon' as being important.

If we had in 2015 what we had today, there might have been a bit of a breakthrough.

ChrisRR

4 hours ago

Because the abundance of javascript has made the web a bloated mess