top | item 25068350

Astonishing Performance of .NET 5

233 points| pjmlp | 5 years ago |alexyakunin.medium.com | reply

286 comments

order
[+] christophilus|5 years ago|reply
It’s been a hot minute since I wrote any C# (pre .NET Core). I kicked the tires yesterday. I have to say, documentation is all over the map, and the old DI / enterprisey boilerplate is still alive and well. Coming from a Node + TypeScript, Ruby, and Go world, C# still feels like a lot of ceremony. So, I gave F# a spin again. It’s always had a special place in my heart. But while the language is fantastic, the tooling (on OS X) and documentation made it difficult to get off the ground.

So, what’s the best-organized resource for getting up to speed on .NET these days?

[+] shireboy|5 years ago|reply
I’m a Dev doing mostly C# and JS. I’ve heard some of the complaints on HN mentioning DI and really don’t get it. I honestly feel like it makes my code cleaner and more testable. For example, I don’t have to care where my IFooService comes from or how best to instantiate and dispose, I just request one in the constructor. For a framework to be flexible, you need _some_ plugin capability. Asp.net seems to do pretty good at giving you nice defaults but letting you swap out with DI. All my dependencies are laid out nicely in one place (Startup.cs) and then used throughout. DI gives you that and I’m glad that it’s baked in now as opposed to having to pick a 3rd party. Maybe I’m biased, though. Help me understand why NOT to use DI? Is it just moving people’s cheese or are there other reasons?
[+] oaiey|5 years ago|reply
Regards ceremony and DI: I think the templates are more Ruby on Rails style while the framework can be trimmed down to nodejs + express simplicity. This sample here is node+express like equivalent (thanks to C# 9.0 top level statements, there is not even a Program class and a Main entry point)

    WebHost.CreateDefaultBuilder().Configure(app => 
    {
        app.UseRouting();
        app.UseEndpoints(e => 
        {
            e.MapGet("/", c => c.Response.WriteAsync("Hello world!"));
            e.MapGet("hello/{name}", c => c.Response.WriteAsync($"Hello, {c.Request.RouteValues["name"]}"));
        });
    }).Build().Run();
I also stumble over that once in a while but I have no hard feeling on it.
[+] rishav_sharan|5 years ago|reply
There is nothing low ceremony in .Net.

I recently ran through the entire ecosystem thinking that there must be something akin to Sinatra (micro web framework) in .Net. Nope. Every single thing is built on top of ASP .net.

I did find a WIP library where they are trying to go for a low ceremony framework https://github.com/featherhttp/framework, but even that is built on top of ASP .net

For me the worst bit about .Net is their treatment of F#. IMO, it is one of the most practical and usable functional languages out there. But none of the official docs have anything on F# at all. Here is an example doc; see if you can find any code example for F#. https://docs.microsoft.com/en-us/aspnet/core/tutorials/razor...

Its always C#. And I have 0 interest in that kitchen sink language.

Between ASP.Net and C# being the entire world for .Net, I have really not much interest in using it for anything. There are plentiful of interesting languages and ecosystems that I can use for my small time projects.

[+] eric_b|5 years ago|reply
The .Net Core documentation is indeed a dumpster fire. As a longtime C# guy I can't even find the up-to-date "blessed" way to do things with ASP.NET anymore. They change it every version it seems. The DI/IoC stuff is definitely too pervasive, particularly in an ASP.NET context.

That said, the new C# language features really do reduce boilerplate when used judiciously - multiple return is now available, "expression-bodied properties", improved template strings etc. Lots of good stuff that is hard to find good documentation for :)

[+] GordonS|5 years ago|reply
I don't really feel like there is that much more boilerplate with C# than there is with TypeScript (although I do like TypeScripts's ctor shorthand that creates members for you from ctor params).

C# 9 also brings top-level programs, which essentially eliminate all ceremony for the entrypoint[0] - an app can now be as simple as:

  using System;
  Console.WriteLine("Hello World!");
[0] https://dotnetcoretutorials.com/2020/08/30/top-level-program...
[+] apalmer|5 years ago|reply
I think it's a result of MicroSoft shifting to the mindset that performance is a feature.

I have been a .Net developer for about 15 years and remember when it was a violation of terms of service to publish .Net performance measurements. Especially performance comparison against Java was something that would get you on Microsoft's bad side real quick.

So it's really I think the difference between performance being a secret, and it being on the front page and Microsoft throwing significant developer resources into it.

[+] codeulike|5 years ago|reply
Not sure how .NET holds up against Java but for the last decade or so its been common knowledge that .NET on Windows was way way faster than most of the interpreted web frameworks out there (PHP, Ruby, etc etc). Compiled vs interpreted, its pretty obvious. This 2013 post about Stackoverflow being served by just two IIS servers is fairly legendary: https://nickcraver.com/blog/2013/11/22/what-it-takes-to-run-...

My point being, I thought .NETs performance was pretty well regarded already fwiw.

edit: here you go, ranking of web frameworks: https://www.techempower.com/benchmarks/#section=data-r19&hw=...

ASP.NET Core 3.1 holds up pretty well, only beaten by C++, Rust, and a Java/Kotlin Framework called Jooby

[+] pjmorris|5 years ago|reply
They used to say 'cycles are free', because, for a long, long time, Moore's law would bail them out.
[+] hollabolla2|5 years ago|reply
In many benchmarks .NET/ASP.NET is faster than GO, a low level language:

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

But unlike GO, you will need to write 50x less lines of code to achieve the same result.

[+] kjksf|5 years ago|reply
Go is faster than .NET and the code is shorter. On average, results may vary.

I looked at the benchmarks.

In cases where .NET is faster it's because the C# version is optimized using unsafe code and x86-specific (i.e. non-portable) AVX2 intrinsics to do the math.

Go version is written in straight-forward way. I think all Go programs are shorter than their C# version.

Compare mandelbrot benchmark:

* https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

* https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Those are not fair comparisons and therefore don't paint the correct picture of relative performance.

[+] gameswithgo|5 years ago|reply
There has long been this perception that Go is a low level language. In the sense that it isn't rich in complicated features, this is true. But it is a garbage collected language, it manages it's own stack which is less low level than C#, and it doesn't provide any low level control over memory/instructions that C# doesn't, less in fact. And the cost to interop with C is higher with Go than with C#.

I think the fact that Go compiles to native executables as the default, just gives the impression that it is "low level". That and the lack of features I suppose.

I say all of this as someone who loves Go as a language by the way. C# could use some simplification!

[+] smarx007|5 years ago|reply
Great, but I would rather see a perf comparison of .NET 5/Core vs .NET 4.7 because .NET Core was a new technology that may have traded performance for features in its first versions. Similar to how JDK 14 beats JDK9..13 but still in many cases is behind JDK8.
[+] oaiey|5 years ago|reply
.NET Framework had a outdated Web stack (System.Web over IIS). In 2014 it was 13 years old with little chance to improve anything without breaking someone. That was the whole reason why .NET Core became a thing.

.NET Core in Version 1.0 cheated then by just taking the network layer of node.js called libuv and linked it up (C -> .NET) . In Version 2.x they wrote and independent socket based networking layer straight in C# which outperformed libuv significantly. In Version 3.x they switched over to use new low level runtime primitives (e.g. Span<T>) which could never have been delivered in the .NET Framework (no breaking changes!). Now in .NET 5 more runtime improvements were added.

[+] resoluteteeth|5 years ago|reply
I think that on the contrary, .net core already had much better performance but less support for some desktop windows stuff, and .net 5 actually added most of the remaining features back.
[+] runevault|5 years ago|reply
Core 2.2 was significantly faster than Framework 4.7+. Core 3.1 was noticeably faster than that, and how .NET 5 is the fastest yet.
[+] rndgermandude|5 years ago|reply
I don't know any definite benchmarks, but anecdote, the unit tests of a bigger library[1] I am writing run in 10s on net5 vs 12s on dotnet 3.1 (core) vs 17s on .net48 (framework), on the same machine with warm caches, of course. That's a sizable difference. YMMV

[1] not web stuff, "plain" C# essentially. It has some compute-bound things like encryption and compression and some fancy tree structures, uses a lot of linq in certain parts.

[+] GordonS|5 years ago|reply
The opposite is true - the .NET5/Core runtimes have optimisations that aren't in .NET Framework CLR.

I haven't come across a package that isn't available for .NET Core in at least a couple of years, I think.

[+] gameswithgo|5 years ago|reply
there are no language features traded. some platform specific libraries are not available on core.
[+] skrowl|5 years ago|reply
We saw about a 45% improvement in our API. EF Core also appears to have improved performance.
[+] y-c-o-m-b|5 years ago|reply
Still slower than Dapper though? I like Dapper and we use it where I currently work, but it enables people to maintain their bad practices brought over from raw SQL. I would like to see EF Core narrow that gap in performance a bit
[+] wffurr|5 years ago|reply
Are there any technical details available as to how this was accomplished? The article is light on details.
[+] gameswithgo|5 years ago|reply
a lot of the standard library has been updated to use simd where possible, there are new features for dealing with memory that let you get c level performance for more things, this has been leveraged to move some things in the standard lib from c to pure c# which plays nicer with the GC for big wins. the jit has also been improving what things can be devirtualized, and linq has had some performance tweaks
[+] RobCrusoe|5 years ago|reply
I find it amazing that there are so many incorrect criticisms of dotnet being made in this thread. It’s honestly as though a number of people with barely any experience with the platform have decided they’re experts and come in to tell everyone else how terrible it is. I shudder to think how many other threads about technologies I know less about also suffer from this affliction.
[+] tokamak-teapot|5 years ago|reply
It’s a shame indeed and I hope this site will improve its ability to boost comments with value to add.

There are some interesting and insightful comments even in those under this article though. I find hiding the entire tree once I see a comment that’s just there for the sake of being negative makes it easier to find the valuable ones.

[+] perlgeek|5 years ago|reply
Did powershell get faster as well?

I remember trying it out (on Linux, that is), and really liked the concept, but it was painfully slow, so it was no fun for me. Like, waiting 3-5 seconds in the REPL for a single line to compile and execute.

[+] oaiey|5 years ago|reply
It will become somewhat faster as soon as it upgrades due to the improvements in the class library. However, I doubt that PowerShell performance relies significantly on .NET itself. It is PowerShell who needs to be implemented efficiently.
[+] jolux|5 years ago|reply
PowerShell has never been that slow for me, if you wouldn’t mind you should probably file a bug about that if you’re still experiencing it. I have found it to start slowly sometimes but once it’s hot I have no performance issues.
[+] majkinetor|5 years ago|reply
Powershell is unbearably slow when Windows Defender is turned on (it is by default).

Kill the bitch and you will have normal times.

[+] BMSmnqXAE4yfe1|5 years ago|reply
Haven't noticed any improvement in my project, but there is just arrays and 4 arithmetic operations. I guess the improvements are in more complex library functions like regex.
[+] fulafel|5 years ago|reply
Has anyone done F# benchmarks?
[+] gameswithgo|5 years ago|reply
In general you should always be able to get the same performance, but you will have to use less idiomatic F#. Then again, the highest performing C# isn't idiomatic C# either.
[+] Stierlitz|5 years ago|reply
I sometimes suspect the whole raison d'être of dot.NET, docker, kubernetes etc, is to render programming into such an esoteric art, that the hoi polloi can be excluded. --

DI == Dependency Injection

[+] simonsarris|5 years ago|reply
This is a minor corner of .NET 5 but I'm bummed that .NET's Blazor (WebAssembly) has no way to interact with the HTML Canvas from C#, so you have to write JS interop code, so its quite slow (that is, C# WebAssembly with Canvas is slower than just writing JS).

My hope was that by the time .NET 5 was out of preview, we would have seen something for this so people could write C# for Canvas in WebAssembly. Alas, not yet!

[+] ksec|5 years ago|reply
On the Subject of Fusion ( Rather than .Net 5 )

Is it basically LiveView on Elixir?

[+] ncmncm|5 years ago|reply
In other news, .NET Core 3.1 was really slow.
[+] unnouinceput|5 years ago|reply
TL;DR - .net 5 vs. .net core 3.51

Personal wish for author (Alex Yakunin) - now compare it with rest (Java mainly).

[+] alexyakunin|5 years ago|reply
Computer Language Benchmark Game already updated their results for .NET / C#: https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

As for me, I wrote https://medium.com/servicetitan-engineering/go-vs-c-part-3-c... that compares C# and Go, and conceptually nothing changed a lot from the moment this was written.

IMO Go is the only viable competitor to .NET nowadays. Java is holding there solely because of Android - performance-wise it's so far behind...

[+] greg7mdp|5 years ago|reply
Must have been astonishingly slow in the first place.
[+] gameswithgo|5 years ago|reply
from the perspective of a rust, c, c++ developer it was a bit slow as all GC based languages are. Before this .net core was already arguably the gc language with the highest performance ceiling.

this can of course depend on workload and whether you care about startup time or throughput vs tail latency etc, but on the whole it tended to allow you beat out java, go and other competitors most of the time.

with AOT being a standard option now, getting quick startup time is easier too, along with the other improvements

[+] robinei|5 years ago|reply
No, in reality 3.1 was actually very fast.
[+] squid_demon|5 years ago|reply
It is not so astonishing that there is any performance improvement when it is 15x slower than it should be in the first place.
[+] GordonS|5 years ago|reply
I'm not sure where on earth you have got this notion from; the .NET Core team have been performance focused for a long time now, and blog posts from the .NET team detailing perf improvements have been posted on HN multiple times.

You even have hardware intrinsics available to play with, and for performance-sensitive libraries such as hashing algorithms, it's typical for performance to come within spitting difference of RAM speed.

[+] gameswithgo|5 years ago|reply
it wasn’t even 15x slower than C

i feel like a lot of people’s ideas about c# performance are from before .net framework 4 which was years and years ago

[+] huhtenberg|5 years ago|reply
This somehow reminds me of an old gamedev trick when at the start of the development cycle you'd declare a huge static array somewhere in the code to "reserve" some memory. You'd then "rediscover" and reclaim it a year later when the game needs to ship but no longer can fit in a memory.

That is, any sort of astonishing improvements is often a sign of the original version being crappy, so it's also a red flag even if it's ultimately the good news.