Remix.run Logo
SeasonalEnnui 4 days ago

The thing I enjoy most about C# is the depth/levels of progressive enhancement you can do.

Let's say in the first instance, you write a proof of concept algorithm using basic concepts like List<T>, foreach, stream writing. Accessible to a beginner, safe code, but it'll churn memory (which is GC'd) and run using scalar CPU instructions.

Depending on your requirements you can then progressively enhance the memory churn, or the processing speed:

for(;;), async, LINQ, T[], ArrayPool<T>, Span<T>, NativeMemory.Alloc, Parallel.For, Vector<T>, Vector256<T>, System.Runtime.Intrinsics.

Eventually getting to a point where it's nearly the same as the best C code you could write, with no memory churn (or stop-the-world GC), and SIMD over all CPU cores for blisteringly fast performance, whilst keeping the all/most of the safety.

I think these new language features have the same virtue - I can opt into them later, and intellisense/analysers will optionally make me aware that they exist.

opticfluorine 4 days ago | parent | next [-]

I have occasionally, just for fun, written benchmarks for some algorithm in C++ and an equivalent C# implementation, them tried to bring the managed performance in line with native using the methods you mention and others. I'm always surprised by how often I can match the performance of the unmanaged code (even when I'm trying to optimize my C++ to the limit) while still ending up with readable and maintainable C#.

panzi a day ago | parent | next [-]

Does this include the GC at the end of it all? Because if that happens after the end timestamp it's not an exact comparison. I read something once about speeding up a C/C++ compiler by simply turning free into a no-op. Such a compiler basically allocates more and more data and only frees it all at the end of execution, so then doing all the free calls is just wasted CPU cycles.

iamflimflam1 4 days ago | parent | prev | next [-]

JIT compilers can outperform statically compiled code by analysing at run time exactly what branches are taken and then optimising based on that.

throw-the-towel 4 days ago | parent | prev [-]

Could you please share some benchmark code? It would be incredibly useful as a learning aid!

pjmlp 4 days ago | parent | prev | next [-]

That is the promise we could already have had in the 1990's with languages like Eiffel, Oberon and Modula-3, and it has taken us about 30 years to finally become mainstream.

C# is not the only one offering these kind of capabilities, still big kudos to the team, and the .NET performance improvements blog posts are a pleasure to read.

4 days ago | parent | prev [-]
[deleted]