Hacker News new | ask | show | jobs
by rossnordby 1483 days ago
I can't comment on the ASP/web side of things, but C# matches up with my atypical use cases extremely well. The high points:

1. Fast compile times for most of development. I'm fine with waiting a while to do a special highly optimized deployment, but getting 95-100% of optimal performance with 0-3 second build times is really nice.

2. Controllable memory access through value types. Nothing getting in the way of C-like contiguous buffers and managing cache line or load alignment.

3. GC that gets out of the way. C# has a GC, but in most of my applications the GC never has to run because I rarely allocate GC-managed instances. It's definitely a nonidiomatic use of C#, but the fact that it's pretty still pretty easy to do is nice. And when I don't have to care about the GC's overhead, the presence of the GC just makes everything easier developmentally.

4. Ability to actually make use of the hardware. The compiler's improved massively in the last several years, and the way vectorization is exposed actually feels a lot nicer than my experiences in C++-land.

And less relevant to my own needs, but still interesting, nowadays you can directly link a C# library into a C/C++/Rust application just like any C library. Among other things.

Almost a decade ago, I was considering exiting the ecosystem in favor of C++/D/not-yet-even-1.0 Rust/etc, but the open source push and a sudden focus on performance basically made the jump unnecessary. C# occupies a really nice sweet spot.

2 comments

Yes! I suspect (but I don't know for sure) that C# has the highest performance sealing of all the VM-based languages with a tracing garbage collector. structs, Span<T> and ReadOnlySpan<T> for type-safe access to contiguous regions of memory allow us to do a lot without touching the heap. C# also has hardware intrinsics for non-cross platform SIMD instructions if you're interested in that kind of thing.
Perhaps it can be manually optimized the best indeed, but the JVM still has a better GC if I’m not mistaken.

Value types are indeed very cool, and I really hope they will get implemented sooner on the Java side as well. Just as a note, Java recently got a SIMD API as well.

You're right; Java has ZGC, a best-in-class garbage collector with average pause times of 50 microseconds while still having great throughput. https://malloc.se/blog/zgc-jdk16#:~:text=With%20concurrent%2...
Can you recommend any resource on how to get into writing high-performant C#?
Pretty much all the standard performance advice from other languages like C/C++/Rust applies. The concepts driving "data oriented design" will get you a long way. The biggest difference is learning how to play nice with the GC- avoiding allocations where necessary, keeping the heap simple so that collections are cheap, or just setting things up so the GC never has to run.

I wrote a bit of stuff a few years ago: https://www.bepuentertainment.com/blog/2018/8/30/modern-spee...

Some of the implementation details (like the operator codegen) are surprisingly outdated now given the speed at which the runtime has moved (and the library is now ~4x faster or something silly like that), but the fundamentals are still there.

Since I wrote that, codegen has improved a lot, the hardware intrinsic vector APIs have offered a way to optimize critical codepaths further, additional cross platform vectorization helpers have made it even easier, NativeAOT is getting close, and all sorts of other stuff. The C# discord #allow-unsafe-blocks channel contains a variety of denizens who might be able to offer more resources.

Thanks! That link especially contains some really helpful write-ups. I never really needed to think much about performance, as my C# usage always was constrained to simple CRUD stuff in server backends, which is a shame really, as it is such a nice language.