[HN Gopher] .NET 6 vs .NET 5 speedup
       ___________________________________________________________________
        
       .NET 6 vs .NET 5 speedup
        
       Author : dgellow
       Score  : 285 points
       Date   : 2021-11-21 11:16 UTC (11 hours ago)
        
 (HTM) web link (alexyakunin.medium.com)
 (TXT) w3m dump (alexyakunin.medium.com)
        
       | Ygg2 wrote:
       | Do be warned that .Net 6 did cause some regressions, in
       | reflection at least
       | 
       | https://github.com/dotnet/runtime/issues/61486
        
         | vadfa wrote:
         | Isn't reflection by definition unstable?
        
           | GordonS wrote:
           | Not so it would crash the entire app with an uncatchable
           | exception, no.
        
           | dtech wrote:
           | No. Reflection is a program accessing or modifying its own
           | program structure. There's not need for it to be unstable,
           | languages like Lisp, Java and I assume C# have clearly
           | defined semantics for it.
        
             | SideburnsOfDoom wrote:
             | Correct.
             | 
             | Perhaps parent comment meant "unstable" in the sense that
             | it turns compile time failures into runtime ones:
             | 
             | e.g. without reflection, if you type "customer.GetOrders()"
             | then it either compiles or does not, whereas reflection
             | code that finds a method called "GetOrders" can compile
             | just fine but you won't know if it finds a method of that
             | name or returns null, until runtime.
        
             | phillipcarter wrote:
             | > There's not need for it to be unstable
             | 
             | In practice there is though, it just depends on what you
             | choose to take a dependency on.
             | 
             | For example, a few years ago the C# compiler did some
             | lambda function optimization work. This broke someone's
             | code because they were using reflection, and ultimately
             | depended on how lambdas were getting optimized prior to the
             | performance improvement in the compiler. The team by-
             | designed that regression, since they make no guarantees
             | that you can depend on a particular implementation detail
             | of how the compiler optimizes things.
             | 
             | That said, when people use reflection in .NET, they're
             | almost always programming against something that is stable
             | and has likely worked the same way for a decade.
        
               | phillipcarter wrote:
               | Also, I can't believe I didn't mention this already:
               | 
               | Reflection in .NET lets you dynamically invoke anything
               | declared internal or private as well. I think it goes
               | without saying that your code can be broken in the future
               | if you do this.
        
       | lvass wrote:
       | How safe, audited and non-invasive is .net core by now? There's a
       | .net program I have a VM for and that's kind of a pain. Since
       | .net had telemetry by default, running bare on my machines was
       | never an option, and Mono wouldn't even work.
        
         | tasogare wrote:
         | In which kind of world do you live that setting a single
         | environment variable is too much technical work?[0] I have the
         | feeling your post is more about shitting on .NET with a low
         | effort excuse than genuine interest.
         | 
         | [0] set DOTNET_CLI_TELEMETRY_OPTOUT environment variable to 1
         | or true
        
         | tester756 wrote:
         | >Since .net had telemetry by default, running bare on my
         | machines was never an option
         | 
         | Why?
         | 
         | I don't see anything weird in data collected
         | 
         | https://docs.microsoft.com/en-us/dotnet/core/tools/telemetry...
        
           | AlexanderDhoore wrote:
           | Medical, military, industrial... Not everything is a webapp.
        
             | tester756 wrote:
             | OP wrote about his private machine.
             | 
             | Anyway, OP was worried about installing .NET because it has
             | telemetry by default, meanwhile you can disable telemetry
             | before running your war-app or just ship standalone? idk.
        
               | lvass wrote:
               | I never said what "my machines" do. Don't assume everyone
               | has the same lax safety necessities as you have.
        
               | tester756 wrote:
               | Fair, that's why I asked which specific telemetry is
               | weird/insecure in your opinion
        
               | nojito wrote:
               | It's downright impossible find a situation where .NET is
               | not approved for use because of "security".
        
         | brushfoot wrote:
         | .NET doesn't have telemetry. The .NET SDK does by default, but
         | that's for developing, not running, .NET apps. You don't need
         | to (and shouldn't) install the SDK on a production machine.
         | 
         | In other words, if you just downloaded the .NET or .NET Core
         | runtime to host an app, there's no .NET telemetry.
         | 
         | As far as the .NET SDK, you can disable telemetry by setting
         | the environment variable `DOTNET_CLI_TELEMETRY_OPTOUT` to `1`
         | or `true`.
        
       | kolleykibber wrote:
       | Are there any figures available for .net usage outside of large
       | organisations?
        
       | Rochus wrote:
       | The speed-up very much depents on the (micro)benchmark in use. I
       | did some measurements using the Are-we-fast-yet benchmark suite
       | which includes both micro and larger benchmarks and got an
       | overall speed-up (geometric mean of factors) of only 2% on x86
       | and even a little speed-down on x64.
       | 
       | See https://www.quora.com/Is-the-Mono-CLR-really-slower-than-
       | Cor... and http://software.rochus-keller.ch/Are-we-fast-
       | yet_results_win... for the details.
        
         | ripley12 wrote:
         | It looks like you're not using the new dynamic PGO
         | functionality (the OP is). I've seen throughput gains of ~15%
         | from that.
        
         | rndgermandude wrote:
         | You're cross-compiling from the Oberon+ language to CLR IL
         | bytecode using your own compiler... This isn't exactly
         | something a lot of people would do. Most people would write
         | more or less idiomatic C# and have the "official" compiler
         | (Roslyn) produce the byte code.
         | 
         | What I am saying, I guess, is that I am not quite sure how much
         | of your benchmark results come down to the quality of IL your
         | custom compiler spits out.
        
           | munchler wrote:
           | As an F# developer, I find it a little frustrating when
           | people assume.NET = C#. If the blog post is about the speed
           | of IL generated by the latest C# compiler, it should say so
           | in the title instead of claiming to measure the performance
           | of .NET in general.
        
             | ygra wrote:
             | The runtime team certainly looks at discrepancies where C#
             | and F# generate different IL that should still run about
             | the same when JIT-compiled. So while C# is the main focus
             | (also since the runtime libraries are written in C#), F# is
             | not forgotten and benefits from a lot of those improvements
             | as well.
        
           | Rochus wrote:
           | > _You 're cross-compiling from the Oberon+ language to CLR
           | IL bytecode ..._
           | 
           | It's just "compiling", not "cross-compiling"; using CLR/CIL
           | as a language backend is an intended feature, that's why the
           | CLR and IL are standardized in ECMA-335 and ISO 23271, and
           | that's why it is called "common language infrastructure".
           | 
           | > _Most people would write more or less idiomatic C#_
           | 
           | You are welcome to write a C# version of the benchmark.
           | 
           | > _have the "official" compiler (Roslyn)_
           | 
           | It's not the "official" compiler, but just the C# compiler
           | implemented by MS and community; there are a lot of other
           | compilers too.
        
             | justin66 wrote:
             | > It's not the "official" compiler, but just the C#
             | compiler implemented by MS and community
             | 
             | That sounds pretty official.
        
             | infogulch wrote:
             | You're arguing semantics. GP's point is that the compiler
             | shipped with the platform may produce better byte code,
             | which could have an affect on the benchmark results. This
             | seems like a reasonable point to make.
        
               | Rochus wrote:
               | Don't forget that IL is not executed, but is just an
               | intermediate representation, and optimizations are done
               | by the CLR; e.g. Mono does the following optimizations
               | (according to e.g.
               | https://man.archlinux.org/man/mono.1.en), regardless
               | which compiler generated the IL:                 branch
               | Branch optimizations       cfold      Constant folding
               | cmov       Conditional moves [arch-dependency]
               | deadce     Dead code elimination       consprop
               | Constant propagation       copyprop   Copy propagation
               | fcmov      Fast x86 FP compares [arch-dependency]
               | float32 Perform 32-bit float arithmetic using 32-bit
               | operations       gshared    Enable generic code sharing.
               | inline     Inline method calls       intrins    Intrinsic
               | method implementations       linears    Linear scan
               | global reg allocation       leaf       Leaf procedures
               | optimizations       loop       Loop related optimizations
               | peephole   Peephole postpass       precomp    Precompile
               | all methods before executing Main       sched
               | Instruction scheduling       shared     Emit per-domain
               | code       sse2       SSE2 instructions on x86 [arch-
               | dependency]       tailc      Tail recursion and tail
               | calls
        
               | forrestthewoods wrote:
               | I don't think you're being very reasonable here.
               | 
               | You made a claim. Someone disputed the validity of your
               | evidence. And your response is "well you can
               | rewrite/replicate my entire project if you like".
               | 
               | I think most people are going to assume your claim is
               | bullshit and move on with their lives. You made the
               | unconventional claim so the burden of proof is on you.
        
               | Rochus wrote:
               | > You made the unconventional claim so the burden of
               | proof is on you.
               | 
               | My assertion is supported by sufficient evidence. The
               | criteria of scientificity are fulfilled. You can repeat
               | the experiment on your system yourself if you wish. Under
               | the referenced links you will find everything necessary
               | to do so.
        
               | fabian2k wrote:
               | You're arguing a very specific subset, which is a
               | completely different thing than what essentially every
               | article on .NET 6 performance claims. The performance
               | claims are almost always about the whole thing, including
               | various parts of the framework, the standard library and
               | lots of low-level optimizations.
               | 
               | Microsoft published an enormously long article detailing
               | many of the optimizations that were done
               | (https://devblogs.microsoft.com/dotnet/performance-
               | improvemen...). And it is not very suprising that pure
               | number-crunching benchmarks only using the .NET IL would
               | not gain very much. As much as I hate to discuss what
               | "real world" applications are, the claims Microsoft and
               | others are focusing on are much more relevant for typical
               | applications where .NET is used than your examples.
        
               | forrestthewoods wrote:
               | The community clearly disagrees.
               | 
               | No one is disputing the results of your test. The
               | question is will those results be replicated under
               | conditions that are relevant to people writing code in a
               | mainstream language under a much more prevalent compiler?
               | 
               | The answer might be yes! Everyone should always be
               | suspicious of microbenchmarks. However people are also
               | wise to be suspicious of benchmarks in obscure languages.
               | 
               | Your results introduce too many new variables for anyone
               | to be comfortable to use it as a data point to inform
               | their decision making.
        
               | infogulch wrote:
               | Nobody is arguing against the results that you got. The
               | question is if the results are applicable to the wider
               | ecosystem or if there is another confounding variable
               | that explains the outcome. Your experiment hints in this
               | direction, and maybe someone should create another one
               | that teases this apart, but definitive arguments either
               | way are premature.
        
               | NationalPark wrote:
               | Maybe consider changing the title? I think most people
               | are reading it as a much stronger claim (applying to
               | Roslyn) than you intended.
        
         | jmkni wrote:
         | Would be interested to see this benchmark on M1 (Apple
         | Silicon), are there instructions on how to run it on that?
        
           | Rochus wrote:
           | If you want to compare different .NET versions running
           | natively on M1 such versions must be available as a
           | precondition. If so, just download e.g.
           | http://software.rochus-keller.ch/Are-we-fast-
           | yet_CLI_2021-08..., update the included runtimeconfig.json
           | file to the .NET version in use and run it (dotnet Main.exe).
        
             | jmkni wrote:
             | Ok nice, will give that a go, cheers :)
        
       | btrask wrote:
       | I might be the last person to realize this, but did Microsoft
       | name it .NET because they already had COM?
        
         | oaiey wrote:
         | It was the year 2000, web services was the hype of the .com
         | bubble. So Microsoft pushed the web services in the net. Hence,
         | all the products .NET. Windows Server .NET, Visual Studio .NET,
         | .NET Framework etc.
         | 
         | It was marketing.
        
         | ygra wrote:
         | .NET actually was known as COM+ for a time before public
         | release. Environment variables for tweaking internal behaviour
         | still retain that moniker.
        
           | randerson wrote:
           | COM+ was basically Distributed COM, and was available for
           | years before .NET. .NET Framework was implemented built on
           | existing Win32 and COM/COM+ calls though, which is why you
           | might see that.
        
             | DenisM wrote:
             | Distributed COM was known as DCOM, COM+ became known as
             | CLR.
        
         | phillipcarter wrote:
         | https://en.wikipedia.org/wiki/Microsoft_.NET_strategy
        
       | jmnicolas wrote:
       | I was so happy with upgrading one of my app to .net 6: I saw
       | perfs gains from 10 minutes execution time on .net 4.8 to 1'30
       | minutes on .net 6.
       | 
       | Then my boss reminded me that we had new hypervisors with SSD
       | (the old one had still spinning platters) so now I'm not so sure
       | the .net 6 upgrade really made my app faster.
        
         | mihular wrote:
         | Highly unlikely that you would gain that much just by
         | upgrading. What kind of an app is anyway?
        
       | dgellow wrote:
       | The library benchmarked in the article is Stl.Fusion:
       | https://github.com/servicetitan/Stl.Fusion. I've only learned
       | about it today, and the documentation is a bit messy, but that
       | seems to be a really interesting project. The author describes it
       | as a .Net library to quickly develop efficient, distributed,
       | real-time web applications.
        
       | Shadonototra wrote:
       | improvements for typical benchmark code
       | 
       | nothing for common user code
       | 
       | why?
       | 
       | because benchmarking JIT code is cheating, nobody runs THE SAME
       | code path 1_000_000 times in a row to warmup the JIT
       | 
       | you run something here, then there, then over there, then
       | sometimes there, this is not JIT proof and you constantly get the
       | JIT to do work
       | 
       | that's part of the reason Go became popular, on top of the single
       | binary and the cloud native libraries story
        
       | notanaverageman wrote:
       | Note that most of the performance improvements come from PGO,
       | which is enabled with following environment variables. PGO is not
       | enabled in .NET 6 by default, but will be in .NET 7 IIRC.
       | set DOTNET_ReadyToRun=0        set DOTNET_TieredPGO=1        set
       | DOTNET_TC_QuickJitForLoops=1
       | 
       | Here are my own benchmarks from a CPU intensive application
       | without any IO and already optimized for allocations. Application
       | runs a task graph either serially or in parallel.
       | .NET 5       --------------------------       |      Method |
       | Mean |       |------------ |---------:|       | RunParallel |
       | 473.4 us |       |         Run | 513.5 us |            .NET 6
       | --------------------------       |      Method |     Mean |
       | |------------ |---------:|       | RunParallel | 452.5 us |
       | |         Run | 499.8 us |            .NET 6 PGO
       | --------------------------       |      Method |     Mean |
       | |------------ |---------:|       | RunParallel | 381.8 us |
       | |         Run | 412.2 us |            .NET 5 - .NET 6     -> ~5%
       | .NET 5 - .NET 6 PGO -> ~20%
       | 
       | Here is what I learned from micro-optimizing a .NET application:
       | 
       | - Use BenchmarkDotNet[0] for general measurements and Visual
       | Studio profiler tools for detailed inspection. They help a lot.
       | 
       | - Memory allocations matter. Using capturing lambdas, LINQ, even
       | foreach on interfaces introduce allocations and slows down the
       | application. You can use ClrHeapAllocationAnalyzer[1] to find
       | these hidden allocations.
       | 
       | - Using abstractions with interfaces and casting back to concrete
       | types cause some overhead, though PGO will probably eliminate
       | most of these.
       | 
       | - Use LINQ cautiously as its variants are mostly slower than
       | explicit coding. E.g. .Any() vs .Count == 0
       | 
       | - Checking Logger.IsEnabled() before calling Logger.Debug() etc.
       | helps a lot. You can even automate this with Fody [2], but it
       | breaks Edit&Continue and possibly .NET Hot Reload too, so it may
       | hinder your productivity.
       | 
       | [0] https://github.com/dotnet/BenchmarkDotNet
       | 
       | [1] https://github.com/microsoft/RoslynClrHeapAllocationAnalyzer
       | 
       | [2] https://github.com/jorisdebock/LoggerIsEnabled.Fody
        
         | vips7L wrote:
         | FYI your chart is very unreadable on mobile.
        
           | notanaverageman wrote:
           | Thanks, I removed unnecessary parts. It should be better now.
        
         | foepys wrote:
         | > - Use LINQ cautiously as its variants are mostly slower than
         | explicit coding. E.g. .Any() vs .Count == 0
         | 
         | When using LINQ also be aware that .First(predicate) is
         | significantly slower than .Where(predicate).First() when called
         | on List<T> and T[]. This is true for essentially all methods
         | like Last, Single, Count etc. Don't trust Visual Studio when
         | it's telling you to "optimize" this.
         | 
         | But if you want the last bit of performance, you shouldn't use
         | LINQ anyways.
        
           | joe_guy wrote:
           | Do you know why that is? That's very interesting.
        
       | tluyben2 wrote:
       | We are testing on .NET 6 now with a large LoC monolithic asp.net
       | system and the results indeed again have improved. We already
       | rewrote a lot when we moved to .net 5 core to be more idiomatic
       | so I guess those things were optimized more. It is not a huge
       | jump but definitely nice work!
       | 
       | Edit; will try to post some numbers when all tests succeed; it is
       | closed source but for a large (millions LoC) codebase I think it
       | is nice to see how it performs under the same conditions compared
       | to our current prod.
        
       | DeathArrow wrote:
       | Quite interesting, but I would like to also see other benchmarks
       | as the author said that the speed is constrained by the DB, ORM
       | and other stack choices.
        
       | mjburgess wrote:
       | In the same vein as what Linus is trying to do now at LTT, it
       | would be useful if there was a "programming journalism" lab which
       | builds "test benches" to create canonical benchmarks and verify
       | the claims made on tech blogs (etc.).
       | 
       | Eg., highly standardised docker builds, on highly standardised
       | hardware, running popular tasks using popular libraries for each
       | "programming tech" (eg., website, stat modelling, event system,
       | ...).
        
         | gostsamo wrote:
         | Usually the setups and architectural choices are so different
         | that it would make more sense for everyone to get a good stat
         | on which functions they are calling and how much and to make a
         | prediction on the individual stats of each function. This does
         | not take into account caching and multithreaded scenarios, but
         | the map can never be the territory.
        
         | okl wrote:
         | Like pts that https://www.phoronix.com/ uses?
        
         | littlecranky67 wrote:
         | There are these: https://www.techempower.com/benchmarks/
        
           | cies wrote:
           | These are some microbenchmarks at best. Still nice to know
           | who wins, but not representative of any real work scenario.
        
             | Hnus wrote:
             | What would be representation of some real work scenarios? I
             | think their test suite covers wide spectrum of operations
             | enough so to be able to draw conclusions from them.
             | 
             | https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Pro
             | j...
        
               | fenring wrote:
               | Unfortunently, after looking at the .net core
               | implementation of this benchmarks, I wouldn't trust it at
               | all. The code is just overengineerd to perform best at
               | benchmark - everything hardcoded, custom routing to cover
               | 2-3 routes with minimal overhead etc. It has nothing in
               | common with real world code.
        
               | the_duke wrote:
               | The Techempower entries are heavily gaming the system.
               | 
               | They often strip out framework functionality and hyper-
               | optimise for the specific benchmark, including things
               | like pre-allocating the exact amount of memory needed to
               | serve the request, not doing route matching et all, etc.
               | 
               | They are basically an exercise in "how clever can we be
               | to win the benchmark" rather than a realistic portrait of
               | real world performance.
        
               | fabian2k wrote:
               | at least for .NET the versions that strip out framework
               | functionality are marked separately, though this part is
               | not that easy to understand if you don't know about it.
               | There are several .NET entries from very low-level
               | without MVC and without ORM up to the full stack.
               | 
               | But still, these benchmarks have their uses but there are
               | a lot of caveats you need to consider when looking at the
               | results.
        
               | The_rationalist wrote:
               | The rust and c++ implementations are only on the top 10
               | because they use PostgreSQL pipelining/batching
        
         | Philip-J-Fry wrote:
         | I think people should just bench their own code and measure
         | their own performance increases.
        
           | [deleted]
        
         | GuB-42 wrote:
         | It is hard to do relevant tests of which language is the
         | fastest.
         | 
         | Really, writing fast code is mostly down to the programmer. For
         | example C is widely recognized as the fastest non-assembly
         | language simply because it leaves a lot to the programmer, C
         | won't magically make your terrible code fast, unless you are
         | using time-to-segfault as a metric. Assembly is the fastest if
         | you know what you are doing, very few know what they are doing.
         | 
         | So, what kind of code are you going to use for your benchmark?
         | Highly optimized code written by experts spending way too much
         | time, the "most idiomatic" code, code written by an average
         | skilled programmer picked at random, code extracted from a big
         | open source project? This can drastically change the ranking,
         | so which one is the most relevant? If you go with the "most
         | idiomatic" for instance, you miss out on the idea that parts
         | can be optimized if needed, and that in real life, programmers
         | aren't perfect and can write suboptimal code by mistake.
         | 
         | There is also a cultural aspect to languages that may not be
         | caught in benchmarks. For example, C programmers tend to have a
         | culture of performance, they tend to know about their hardware,
         | will try to save memory, make data structure efficient, etc...
         | Python programmers, not so much, instead they tend to value
         | readability and development time.
         | 
         | You can't test languages like you test CPUs for instance. With
         | CPUs, you just run the same code on them and time them. You
         | can't do that for obvious reasons: your C compiler won't accept
         | your Python code, it is necessarily an apples to oranges
         | comparison.
        
           | DeathArrow wrote:
           | In general the speed is lost because we make the CPU consume
           | cycles to do things that are not necessary in order to solve
           | a particular problem:
           | 
           | -unneeded allocations
           | 
           | -boxing/unboxing
           | 
           | -garbage collection
           | 
           | -interpreting
        
           | kaba0 wrote:
           | > Assembly is the fastest if you know what you are doing,
           | very few know what they are doing.
           | 
           | Just a nitpick but for any reasonably sized code, no. While
           | some people can indeed do impressive optimizations on small
           | segments of assembly, they are humans and they will fail to
           | do trivial optimizations that are reliably done by compilers.
        
         | buryat wrote:
         | why someone would do it fo free? with journalism you have
         | advertiser that sponsor investigations albeit undirectly
        
           | Dayshine wrote:
           | LTT is a perfect example of how you can do it without any
           | particularly plausible conflicting sponsorships.
           | 
           | Do you really believe that Merch sales and sponsorship by
           | Squarespace, VPN providers, sys-admin software, etc influence
           | their coverage of CPUs?
        
       | mikewarot wrote:
       | What does .NET actually do?
        
         | cyral wrote:
         | It is basically the standard library for C#/F#/VB.NET
         | applications.
        
           | mikewarot wrote:
           | I've never had to use it in my code, but I've had plenty of
           | problems with its use in applications. It always seemed to me
           | that it was Microsoft's attempt to lock people into Windows
           | forever.
        
             | hu3 wrote:
             | .NET Linux support was announced a few years ago.
             | 
             | > It always seemed to me that it was Microsoft's attempt to
             | lock people into Windows forever.
        
             | cyral wrote:
             | > It always seemed to me that it was Microsoft's attempt to
             | lock people into Windows forever.
             | 
             | It has had first-class support for Linux and MacOS for the
             | past five years so that certainly isn't the case these
             | days. actually develop C# applications on Mac and run them
             | in production on Ubuntu, no Windows involved in the
             | toolchain anymore.
        
         | Rapzid wrote:
         | .NET is an umbrella term for the platform ecosystem that
         | includes, among other things:
         | 
         | * Common Language Runtime(aka CLR, aka runtime) and its JIT
         | compiler RyuJIT
         | 
         | * The C# language and it's compiler Roslyn
         | 
         | * The base class library and framework class libraries(aka BCL
         | and FCL)
         | 
         | * ASP.NET the flagship web application framework
         | 
         | * F# the platforms flagship functional language
         | 
         | * etc etc
         | 
         | It's all ".NET"
        
       | creamytaco wrote:
       | Is .NET relevant even on Windows these days? With MSFT's Linux
       | embrace ever tightening, why would anyone without sunk costs
       | invest in .NET when every alternative seems to be better (or
       | quickly getting there)?
        
         | [deleted]
        
         | Beltiras wrote:
         | Those sunk costs are sometimes a dev team. Not just a matter of
         | spent money.
        
           | jcims wrote:
           | That's exactly the issue I'm facing now. Have a team of .NET
           | devs who feel like the walls are closing in because the
           | corporate strategy is clearly elsewhere. My goal for now is
           | to focus on moving off of Windows because that's actually
           | where all of our pain comes from.
        
             | Beltiras wrote:
             | I'm leaving my current workplace because we are making the
             | switch the other way around. Having spent 3 years retooling
             | everything for Docker and containers we just got a new boss
             | that's slowly moving more in the Windows direction.
             | Sometimes it's also just a case of being too entrenched.
             | And then there are all the stakeholders that don't
             | understand the tech but have way more say in what gets
             | chosen than us techies.
        
         | quietbritishjim wrote:
         | The developer experience for .NET is pretty incredible. Have
         | you tried it? I don't think you would be dismissing it like
         | this if you had.
        
           | xbar wrote:
           | I, for one, have not, but I keep hearing this from HN.
           | Perhaps the next project....
        
           | 9wzYQbTYsAIc wrote:
           | For real, .NET's problems these days are mostly related to
           | being controlled by Microsoft and the .NET Foundation.
           | 
           | Definitely some room to grow in the technical respects, but
           | the .NET ecosystem is pretty decent, as it is.
        
         | gameswithgo wrote:
         | Better how? C# is probably the best performing gc language
         | there is, and F# probably the most interesting.
        
         | thrower123 wrote:
         | If you're doing Windows development, you'd be foolish not to
         | use dotnet. It's pretty good off Windows now, with all the
         | massive efforts they've put in making it run on Linux better
         | than Mono did the past years.
        
         | GordonS wrote:
         | > when every alternative seems to be better
         | 
         | Eh?
         | 
         | C# and F# are fabulous languages - it's a huuuge stretch to
         | claim that almost anything else is "better".
        
         | thepra wrote:
         | I have a web app running on it on Linux :)
        
         | jb_s wrote:
         | As a .NET veteran, if anything .NET is 10x more relevant now
         | that it's cross-platform... you don't need Windows to develop,
         | you can containerise your apps and run it anywhere, it's
         | _significantly_ better now than in the old days (anyone
         | remember debugging GAC issues?)
         | 
         | C# is still one of the best languages I've used, which is the
         | reason why I've kept at it for so long - e.g. it got
         | async/await semantics in like 2012 (just after F# did). I'm
         | about to switch jobs to a company that uses Typescript/Node
         | after years in .NET and I feel like I'm going to miss quite a
         | lot of the development experience. I'm not sure which
         | alternatives are necessarily better but again I haven't spent a
         | significant amount of time with, for example, Golang or Scala.
         | Swift was kind of equivalent but (AFAIK) missing some features
         | and the vastness of the nuget package ecosystem.
        
         | ozim wrote:
         | I would say that you see it from different perspective.
         | 
         | It is Windows/Linux that are becoming irrelevant.
         | 
         | Future is about browser applications/mobile applications and
         | cloud workloads.
         | 
         | Yes of course there are uses for desktop computing but those
         | are specialists.
         | 
         | While general public will be using phones and tablets not even
         | owning a laptop. On the phone/tablet people don't even care
         | what is the OS.
         | 
         | I already know people who don't have computers at home, only
         | tablets/phones/gaming consoles. Normal people want to play
         | games, message each other, no one cares about OS an Microsoft
         | knows that.
        
         | pjmlp wrote:
         | Yes it is, even with all the COM love, there were only three
         | C++ talks on the VS2022 release party, .NET stole the show for
         | everything else.
         | 
         | Most desktop applications targeted at Windows are written in
         | .NET and C++ only comes into the picture via COM/DLLs, hardly
         | anyone writes pure Windows applications in straight C or C++,
         | unless we are talking about games.
        
           | Aerroon wrote:
           | And even Unity games are C#.
        
         | ClumsyPilot wrote:
         | "NET when every alternative seems to be better"
         | 
         | Better how? There are people convinced that C is the best
         | because it's the fastest, and if that the only thing thst
         | matters to them, they aren't wrong.
        
           | kaba0 wrote:
           | But not even that is true. C is not any closer to metal than
           | C++, or bunch of other languages that compile to native code
           | are, hell, it can't even do proper threading natively, nor
           | SIMD, which is just a bunch of compiler specific pragmas.
        
         | Semaphor wrote:
         | .NET nowadays runs on Linux. Even SQL Server does.
        
           | creamytaco wrote:
           | Running on Linux doesn't tell us much in itself. Can it
           | compete with long-established alternatives on that platform?
           | Does it have adoption? I think the answer to both these
           | questions is a strong no.
        
             | Rapzid wrote:
             | I know the answers are yes.
             | 
             | Since we are on the topic of Linux so something exciting
             | was merged for .Net6 that wasn't talked about; the new file
             | interface with support for symbolic links. That sounds a
             | bit absurd but it's been a long standing issue with
             | challenges you wouldn't expect..
             | 
             | https://github.com/dotnet/runtime/pull/54253
        
             | nycdotnet wrote:
             | At Namely our payroll and benefits systems run on .NET in
             | Linux containers on k8s talking to Postgres, SQL Server,
             | Redis, and Kafka, and we integrate between these services
             | and others via gRPC. Some of these services' endpoints are
             | exposed via GraphQL using a Node service running the Apollo
             | server and some are called directly via gRPC by Go, Ruby,
             | and Python services. All of this is on Linux in k8s. The
             | .NET services integrate with the same ELK stack and things
             | like Jaeger. It has adoption, it is competitive, and it
             | integrates really nicely.
        
               | strikelaserclaw wrote:
               | do u guys use ef?
        
             | Semaphor wrote:
             | I'm not sure if that's what you mean, but your comments
             | sound like "I have absolutely no idea, but I'm going with
             | my unfounded gut feeling"
        
             | fabian2k wrote:
             | Why shouldn't it be able to compete there? It works very
             | well on Linux and modern .NET is a pretty good platform in
             | many regards.
        
             | 9wzYQbTYsAIc wrote:
             | It certainly has the potential for both.
             | 
             | There are scores of Windows developers who's skills are now
             | transferable to Linux, Apple, and Android development
             | (albeit with some caveats).
        
               | kreeben wrote:
               | I had to raise two kids so I couldn't find time to master
               | both the Linux and Windows ecosystems so I chose the one
               | they use at work. These days Microsoft has made me think
               | more carefully about choosing platform and with their new
               | proposals, Win11 and Edge The E-commerce Browser, I'm
               | ready to jump onto Linux but how would I program that
               | environment, when I have almost no experience in C? For
               | me, the answer is .net.
               | 
               | Thank you, Microsoft, for showing me a way out.
        
               | 5e92cb50239222b wrote:
               | Eh? you don't have to know C to develop for Linux. Most
               | of us don't write C at all. I've written maybe a few
               | thousand lines in all my life, the vast majority of them
               | for ESP32.
        
               | kreeben wrote:
               | Of course one doesn't have to program one's environment
               | but I would never be on one where I couldn't.
        
               | ogogmad wrote:
               | I think you misunderstood the parent commenter. He said
               | that he hasn't programmed much _in C_ , but that doesn't
               | mean he hasn't done much programming altogether. He's
               | wondering why you ever felt that programming in Linux
               | meant you had to use C. Many of the Linux APIs are
               | written in C but there are wrappers for countless other
               | languages, no?
               | 
               | Many Linux people like to use Python, for instance.
               | Unfortunately, it's a slow language for all sorts of
               | incidental but hard-to-fix reasons. This has led people
               | to look for alternatives. I think Go is increasingly used
               | as an alternative, but it lacks features like operator
               | overloading which are a necessity in certain areas.
               | There's JVM languages like Java, Kotlin and Scala as
               | well. Nim is up-and-coming. Some people use functional
               | languages like Haskell and Common Lisp. C++ is widely
               | used but not much loved.
        
               | kreeben wrote:
               | Thx, yes I might have. I know enough about all of those
               | languages that you mentioned to realize, as a c-sharper I
               | have it good. Java is a bit too weird for me. Python a
               | bit too slow. C++ too hard, Haskel too functional ;)
               | 
               | I realize of course that not all Linux users are C
               | programmers.
               | 
               | Given the opportunity to transfer my C# knowledge over to
               | Linux, I'll take it.
        
             | oaiey wrote:
             | Check the techempower benchmarks mentioned all over any
             | .NET performance article. They beat on Linux nearly any
             | other tech stack in the performance game. NFRs like
             | debugging, monitoring, etc are all there.
             | 
             | From my personal perspective, roughly 75% of all applicable
             | (non-Windows-UI) .NET greenfield project go straight on
             | Linux. The brownfield/maintenance situation is surely
             | different. Companies are not married to the Windows stack
             | when you get the alternative for free. And R&Ds just follow
             | that.
             | 
             | .NET is on Linux and performs excellent there.
        
               | 5e92cb50239222b wrote:
               | Those benchmarks are a joke. Did you look at the source
               | code? Nobody is writing real applications like that. Most
               | of them do a single select and push the results out to
               | the client.
               | 
               | (FWIW, I spend about 40% of my working time dealing with
               | dotnet).
        
               | sp33der89 wrote:
               | And how has your experience with dotnet been?
        
             | cyral wrote:
             | Yes, I run it in production on Linux and develop on Mac and
             | the experience is great. You would be correct making this
             | statement 5 years ago before they re-wrote everything to be
             | cross platform (that is what .NET Core is vs the old .NET)
        
       | sp33der89 wrote:
       | I've seen the posts about all the speedups each new version of
       | .NET gets and I'm just wondering, was .NET just alright in
       | performance before all this? Is that the reason they can get all
       | these speedups? :P
       | 
       | I'd be interested in some JVM vs .NET 6 benchmarks too, which
       | platform to chose when.
       | 
       | EDIT: I know about the benchmarks and I also feel like sometimes
       | these benchmarks are really optimized in a non-idiomatic way. I
       | would love to know how performance idiomatic Java/.NET code is
       | and if one is to start a new project today why one would choose
       | the JVM over .NET or when someone would chose .NET over JVM.
        
         | Semaphor wrote:
         | It's not the same, but there is this well-known framework
         | benchmark [0], it always had the .net frameworks close to the
         | top.
         | 
         | I'm guessing a lot of the speedups come from getting rid of
         | legacy cruft. With .net core/.NET 5/6 they got rid of a lot of
         | things compared to .NET Framework 4.8 and could play with
         | optimizations that simply weren't doable before. That's just me
         | guessing, though ;)
         | 
         | [0]: https://www.techempower.com/benchmarks/
        
           | rndgermandude wrote:
           | It's that in part. Here are some of my additional
           | observations and or guesses.
           | 
           | They invested a lot of time adding language features with
           | compiler and runtime support to avoid e.g. heap
           | allocations/copying, like Span<> and friends, (readonly) ref
           | structs, in/ref/out parameters (ref and out parameters
           | existed before but were used a lot less in the runtime), or
           | ValueTasks to some degree. This in turn enabled a lot of
           | potential for optimizations in the compiler (aside from
           | essentially writing an entirely new bytecode compiler with
           | Roslyn and entirely new JIT with RyuJIT, throwing out the
           | crufty old compilers), in the general runtime, and in the
           | specific runtimes/frameworks e.g. ASP.NET. Those
           | optimizations have to be implemented first however, and more
           | and more get implemented with each new version.
           | 
           | I have a project I maintain that sees an almost 50% speedup
           | from net48 to net5, and another 10-15% speedup from net5 to
           | net6 (based on the time it takes to run the extensive test
           | suite). It isn't even that compute heavy. From profiling it
           | appears that a lot of these speedups are due to internal
           | copies of data being avoided, and a lot of additional fast-
           | paths in the runtime (e.g. fast-paths for byte-arrays or
           | character-arrays as opposed to taking the generic array slow
           | paths).
           | 
           | Another thing of note is that they added a lot of `bool
           | Try*(..., out result)`-style APIs meant to avoid exceptions
           | and the associated handling, and switched a lot of internal
           | code to use these functions. E.g. in the reference source of
           | the net48 runtime I think there are still a lot of instances
           | of                  try {          var number =
           | int.Parse(value);        }        catch {          // slow
           | path/error path        }
           | 
           | instead of the new-idiomatic .netcore and later style of
           | if (!int.TryParse(value, out var number)) {          // slow
           | path/error path        }
           | 
           | try-catch was/is slow-ish, and throwing exceptions is too,
           | aside from it preventing inlining by the JIT a lot of times.
           | 
           | And while #nullable (source annotations for what is nullable
           | or not) and associated annotations such as MaybeNullWhen()
           | had no direct influence on how the compiler could optimize,
           | it probably helped people a lot writing correct code and as a
           | side effect a lot more code became compile-time provable non-
           | nullable which enabled further optimizations e.g. generating
           | code that skips redundant null checks.
        
             | chrisoverzero wrote:
             | > the new-idiomatic .netcore and later style
             | 
             | `Int32.TryParse` has existed since .NET Framework 2.0,
             | which was released on February 13, 2002:
             | https://docs.microsoft.com/en-
             | us/dotnet/api/system.int32.try...
        
               | rndgermandude wrote:
               | Right, this one has, a lot of other public or runtime-
               | internal Try* methods have not.
               | 
               | And even tho this particular one has existed for a long
               | time, that doesn't mean it was used consistently in the
               | runtime or in the popular first and third party
               | frameworks.
               | 
               | I'd argue the Try*-style, while artifacts of it were
               | present before already, only really became widely
               | idiomatic with dotnetcore.
        
               | cyral wrote:
               | Surprising that in 2021 Java still doesn't have this in
               | its standard library
        
             | CornCobs wrote:
             | Honestly I really like C#'s outvar and return success
             | idiom. It's soooo ugly and yet slick at the same time. C
             | does the same thing but I think the inline out var
             | declarations make a huge difference to using them. Of
             | course you miss out on error context an Exception or
             | Result<T, Err> gives you but for many of the Try* functions
             | it really doesn't matter.
        
           | foepys wrote:
           | .NET Core also introduced some new CLR features that are
           | incompatible with the CLR used in .NET Framework. Span<T> for
           | example.
           | 
           | This has happened before with .NET Framework 2, 3, 4 etc. but
           | instead of making a .NET Framework 5 they rather made .NET
           | Core cross-plattform and threw backwards-compatability-at-
           | all-cost out of the window. While all .NET Framework
           | applications (except the ones that do naughty stuff with
           | reflection) that were compiled for .NET Framework 4.5 behave
           | the same way on .NET 4.8, .NET (Core) got rid of this and
           | lets developers bundle the CLR directly, giving them more
           | leeway for incompatible changes.
        
         | 9wzYQbTYsAIc wrote:
         | .NET used to be considered a little bit slow, especially when
         | using the Reflection related features, but not nearly as slow
         | as interpreted languages.
        
         | Bayart wrote:
         | Most of the performance gains are really in the middleware (for
         | example Entity Framework) and getting rid of pre-.NET Core
         | legacy cruft rather than the VM, AFAIK.
        
         | gameswithgo wrote:
         | .NET has been faster than Java on most of the benchmarkgame
         | benchmarks for a while, since .net core 3 or so.
         | 
         | More specifically though the JVM has tended to be better about
         | optimizing naive code than .net while .net has tended to offer
         | more tools to do your own optimizing (unsafe, simd, value
         | types, etc). So it would be interesting to see if the
         | performance of naive code has improved relative to Java lately
        
           | Mikeb85 wrote:
           | > benchmarkgame benchmarks
           | 
           | Lol look at the code. N-body for example, the C# is horrific
           | C-in-C# code with a million optimizations (just read the
           | comments lol), the Java code is idiomatic and not optimized
           | at all.
        
             | symbol-mason wrote:
             | Well the fastest C# entry for n-body looks like a
             | translation of the C/C++ versions. It is a meaningful
             | result that the primitives of the language allow for it to
             | hang in that company. The absence of a Java version using
             | numerics is unfortunate, that'd be a nice addition.
             | 
             | A lot of the coding style seems optimized around copy-
             | pasting the C code, e.g. trying to alias the Vector methods
             | (Vector256.Create) to their instruction name
             | (_mm256_set1_pd). That makes the code non-idiomatic, but it
             | also doesn't really help performance, just makes the
             | porting easier.
             | 
             | The F# example is on the same runtime and a better view of
             | using the numerics directly. As a trade-off of performance,
             | memory, and code complexity it is actually a pretty solid
             | balance, which I wouldn't have expected.
             | 
             | https://benchmarksgame-
             | team.pages.debian.net/benchmarksgame/...
        
               | Mikeb85 wrote:
               | How is it meaningful?
               | 
               | I can inline C code in Ruby, does that mean Ruby is as
               | fast as C now?
               | 
               | I'd much rather see a comparison of idiomatic code in
               | different languages. When I choose a language to build
               | something in I'm not thinking "How can I write C in this
               | language?"...
        
           | sp33der89 wrote:
           | Yeah, I would love it if I could just write idiomatic code
           | for the platform and it'd be just fast enough!
        
           | kasperni wrote:
           | > .NET has been faster than Java on most of the benchmarkgame
           | benchmarks for a while, since .net core 3 or so.
           | 
           | And which benchmarks games are those? If I go to to the
           | Techempower benchmark and select only C# + Java. Java comes
           | on top in every individual category of all the benchmarks.
           | 
           | I'm not claiming that Java is faster than .NET. Just that I
           | don't believe one platform is significantly faster than the
           | other.
           | 
           | [1] https://www.techempower.com/benchmarks/#section=data-r18&
           | hw=...
        
             | grumpyprole wrote:
             | Such programs are often specially and painstakingly
             | constructed to avoid all the commonly used language
             | features that are inefficient. For example, in Java, user-
             | defined data types are heap allocated and generic code
             | boxes everything, even primitive types (an ArrayList of
             | ints becomes unfortuately an array of pointers).
             | 
             | Are these programs benchmarking typical idiomatic Java, or
             | just some subset of the language?
        
               | CraigJPerry wrote:
               | >> Are these programs benchmarking typical idiomatic Java
               | 
               | https://benchmarksgame-
               | team.pages.debian.net/benchmarksgame/...
               | 
               | c# regex redux - 1.42 seconds
               | 
               | java regex redux - 5.31 seconds
               | 
               | Ok... but looking at the code:
               | 
               | https://benchmarksgame-
               | team.pages.debian.net/benchmarksgame/...
               | import java.io.*;         import java.util.*;
               | import java.util.concurrent.CompletableFuture;
               | import java.util.Map.Entry;         import
               | java.util.function.*;         import java.util.regex.*;
               | import static java.util.stream.Collectors.*;         ...
               | 
               | It's only using vanilla Java features.
               | 
               | c# ?                   ...         using
               | System.Runtime.InteropServices;         ...
               | 
               | Interesting, why does it need that?
               | [DllImport("pcre2-8", EntryPoint = "pcre2_compile_8",
               | CharSet = CharSet.Ansi)]             extern static IntPtr
               | PcreCompile(string pattern, long length, uint options,
               | out int errorcode, out long erroroffset, IntPtr
               | ccontext);                  [DllImport("pcre2-8",
               | EntryPoint = "pcre2_jit_compile_8", CharSet =
               | CharSet.Ansi)]             extern static int
               | PcreJitCompile(IntPtr code, uint options);
               | [DllImport("pcre2-8", EntryPoint = "pcre2_jit_match_8",
               | CharSet = CharSet.Ansi)]             extern unsafe static
               | int PcreJitMatch(IntPtr code, byte* subject,
               | long length, long startoffset, int options, IntPtr
               | match_data, IntPtr mcontext);
               | [DllImport("pcre2-8", EntryPoint =
               | "pcre2_match_data_create_8", CharSet = CharSet.Ansi)]
               | extern unsafe static IntPtr PcreMatchDataCreate(uint
               | ovecsize, IntPtr mcontext);
               | [DllImport("pcre2-8", EntryPoint =
               | "pcre2_get_error_message_8", CharSet = CharSet.Ansi)]
               | extern unsafe static int PcreGetErrorMessage(int
               | errorcode, StringBuilder buffer, long bufflen);
               | [DllImport("pcre2-8", EntryPoint =
               | "pcre2_get_ovector_pointer_8", CharSet = CharSet.Ansi)]
               | extern unsafe static IntPtr PcreGetOvectorPointer(IntPtr
               | match_data);                  [DllImport("pcre2-8",
               | EntryPoint = "pcre2_substitute_8", CharSet =
               | CharSet.Ansi)]             extern unsafe static int
               | PcreSubstitute(IntPtr code, byte* subject,
               | long length, long startoffset, int options, IntPtr
               | match_data, IntPtr mcontext,                 byte*
               | replacement, long rlength, byte* outputbuffer, out long
               | outlength);
               | 
               | Aha! It's because the c# impl is really just a wrapper
               | round a native C impl of the problem.
               | 
               | In what world is this a useful comparison?
               | 
               | The fastest "real" c# solution is still faster than the
               | java one though:
               | 
               | c# (real) - 3.1 seconds
               | 
               | https://benchmarksgame-
               | team.pages.debian.net/benchmarksgame/...
        
               | grumpyprole wrote:
               | I agree it's not a useful comparison. That's why I don't
               | give much weight to statements such as "Java comes on top
               | in every individual category of all the benchmarks".
        
               | zigzag312 wrote:
               | I agree. That's really not usefull comparision. They
               | should create categories for each benchmark, like:
               | - very naive code (shortest, most readable & easy to
               | write code)            - idiomatic code            -
               | optimized code without other-language-libs wrappers and
               | without SIMD, single threaded            - optimized code
               | without other-language-libs wrappers and without SIMD,
               | multi-threaded            - optimized code without other-
               | language-libs wrappers and with SIMD and/or multi-
               | threaded            - optimized code with other-language-
               | libs wrappers allowed and any other optimization
               | technique
        
               | gameswithgo wrote:
               | Yes any benchmark will be invalid for some people, such
               | is life. If you want to claim or know something specific
               | you will have to so your own painstaking investigation or
               | find someone who has done that work.
               | 
               | benchmarkgame does not attempt to compare idiomatic
               | solutions for languages, it is closer to a "what is the
               | best you can do" benchmark
        
               | grumpyprole wrote:
               | > It is closer to a "what is the best you can do"
               | benchmark
               | 
               | As I suspected. So of course this tells us very little
               | about how fast idiomatic code is relative to other
               | languages. "The best I can do" is to invoke hand
               | optimised assembly language, but rarely is that the right
               | choice.
               | 
               | A much more useful test would involve benchmarking some
               | similar real world apps that solve the same problem.
        
               | vips7L wrote:
               | Generic boxing should be fixed "soon" if they ever
               | release Valhalla.
        
             | torginus wrote:
             | While I'm not super familiar with the Java world, none of
             | the frameworks that have a significant advantage sound
             | familiar to me - I'm not sure how mature are they, whereas
             | Asp.NET is _the_ solution for writing servers under .NET.
        
             | zigzag312 wrote:
             | > And which benchmarks games are those?
             | 
             | https://benchmarksgame-
             | team.pages.debian.net/benchmarksgame/...
             | 
             | Be aware that many implementations on benchmarksgame are
             | much lower-level and using all kind of performance tricks
             | than what you would normally write.
        
               | merb wrote:
               | well the same for techemporer benchmarks. sorry but some
               | of that stuff is as shady as the benchmarksgame. I really
               | don't get it, why people don't create 100% benchmarks
               | instead of specialized ones.
        
             | DonHopkins wrote:
             | Java's performance hasn't really mattered since Oracle took
             | it over. There are things MUCH worse than poor performance,
             | and being owned by Oracle is one of them.
        
               | ptx wrote:
               | Ownership by Microsoft isn't great either, unless you
               | enjoy jumping through hoops to disable their
               | telemetry[1].
               | 
               | [1] https://github.com/dotnet/sdk/issues/6145
        
             | jayd16 wrote:
             | IMO that link makes .NET look very good. Aspcore, the
             | straight off the shelf, obvious choice, is the best
             | performing .net server? It beats Jetty and Spring but loses
             | to a long tail of less popular frameworks
        
             | symbol-mason wrote:
             | You're looking at pretty old results, round 18 was in 2019.
             | I also don't think that boutique web frameworks say much
             | about the strength of the underlying language or runtime
             | (e.g. look at just.js).
             | 
             | What in the Java world is in the same maturity tier as
             | ASP.NET is open to opinion, but at least local Java devs
             | seem to consider Spring or Micronaut as sane defaults, and
             | of course modern ASP.NET runs circles around those.
             | 
             | https://www.techempower.com/benchmarks/#section=test&runid=
             | 9...
        
             | gameswithgo wrote:
             | This: https://benchmarksgame-
             | team.pages.debian.net/benchmarksgame/...
             | 
             | techempower is isolated to web framework testing as far as
             | I know
        
         | thrower123 wrote:
         | One SQL query going over the network will so dominate any
         | micro-optimizations in the framework that it's a little silly
         | for most of us to listen too closely when the ASP.NET team says
         | they've sped up request processing another 40%. If JSON parsing
         | request bodies and reading headers are significant, an API
         | generally isn't doing very much.
        
         | oaiey wrote:
         | There are two things:
         | 
         | (1) .NET Framework was slow and had some bad habbits (e.g. heap
         | allocations, reflections, little optimizations, etc) ...
         | especially the web stack. .NET Core/.NET fixes that, issue by
         | issue. And since .NET is historically very close to the
         | underlying platforms, we now see competitive outcomes (to e.g.
         | Go, C++, etc).
         | 
         | (2) Performance = lower CPU/Memory Allocation = more throughput
         | = lower Cloud costs. At scale, that makes a huge difference.
        
         | bob1029 wrote:
         | > was .NET just alright in performance before all this
         | 
         | For some niche applications (i.e. financial exchanges), .NET 5
         | [was/is] arguably the fastest way to implement certain ring
         | buffer abstractions because of its interesting blend of
         | performance and safety. There is a variant of the LMAX
         | Disruptor developed for .NET which leverages the value
         | semantics of the C# struct to push things beyond what the Java
         | implementations are capable of [0].
         | 
         | Certainly, with enough resources and manual memory management,
         | you could best the C# implementations using a C/C++/ASM
         | codebase, but this is a tenuous tradeoff with practical risks
         | that must be accounted for.                 [0]
         | https://medium.com/@ocoanet/improving-net-disruptor-
         | performance-part-3-introducing-the-valuedisruptor-5b467730bbe
        
         | fnord123 wrote:
         | Software benchmarks are super subjective. Michael Larabel at
         | Phoronix and Isaac Gouy of the benchmark game have done a lot
         | in this area. But everyone says you need to take it with a gain
         | if salt (which is often true).
         | 
         | There's also TPC-C benchmark suites where people benchmark
         | their own software and claim results. Not really independent
         | journalists there.
        
           | Rochus wrote:
           | > Software benchmarks are super subjective.
           | 
           | No, they are not, but they are just a measurement tool, not a
           | source of absolute truth. When I studied engineering at ETH
           | we learned "Who measures measures rubbish!" ("Wer misst misst
           | Mist!" in German). Every measurement has errors and being
           | aware of these errors and coping with it is part of the
           | engineering profession. The problem with programming language
           | benchmarks is often that the goal is to win by all means; to
           | compare as fairly and objectively as possible instead, there
           | must be a set of suitable rules adhered to by all benchmark
           | implementations. Such a set of rules is e.g. given for the
           | Are-we-fast-yet suite (https://github.com/smarr/are-we-fast-
           | yet).
        
             | fnord123 wrote:
             | It's subjective because it can't be used as a source of
             | truth. Of course "I measured X and my results were Y using
             | methodology Z" can be a statement of fact but X and Z are
             | where the subjectivity lie.
             | 
             | For example, benchmark game allows for warmups and so does
             | awfy. This favors jits because it allows them to warm up
             | when they would otherwise be slower. This might give the
             | mistaken impression that java is a great choice for command
             | line tools due to the performance characteristics.
             | 
             | In contrast, most benchmarks I've seen don't use profiler
             | guided optimizations for C or C++. Hence the subjectivity.
             | 
             | And the claim of only wanting idiomatic code in awfy. This
             | is, of course, subjective as well.
        
               | kaba0 wrote:
               | Last I checked benchmark games didn't care about warmups.
        
               | fnord123 wrote:
               | You could be correct. The point doesn't rely on what a
               | specific benchmark collection in particular does but that
               | there is an open discussion on what is appropriate in the
               | context of what people using the results find important.
        
               | [deleted]
        
         | jb_s wrote:
         | C# was never _really_ slow in the same way as python, etc. And
         | anyway 99% of the time you 're gonna be slow because the sack
         | of meat writing the program screwed up some aspect of the
         | system design or the code. Unless you're using something really
         | shit-tier for perf.
         | 
         | The gap closed significantly with .NET core, which is why
         | everyone was quite surprised when .NET 5 (the next iteration)
         | had a fairly significant speedup in many scenarios.
         | 
         | For reference, Stack Overflow was running on .NET MVC on like 2
         | servers pretty recently (with some auxiliary infrastructure for
         | CDN and search) and using MS SQL.. I think it might still be
         | running on this setup but not 100%. Honestly I have no idea how
         | they do it on a .NET monolith but there you go.
        
           | [deleted]
        
           | deanward81 wrote:
           | Stack Overflow runs on 9 web servers with (iirc) 48 logical
           | cores (2 x 12-core Xeons) and 64GB RAM. Those servers are
           | shared by a few apps (Talent/Job, Ads, Chat, Stack
           | Exchange/Overflow itself) but the main app uses, on average,
           | ~5% CPU. Those machines handle roughly 5000 requests/sec and
           | were running .NET 5 as of September 2021 (when I moved on).
           | That's backed by 2 v. large SQL clusters (each consisting of
           | a primary read/write, a secondary read-only in the primary DC
           | and a secondary in the failover DC). Most traffic to a
           | question page directly hits SQL - cache hit ratio tends to be
           | low so caching in Redis for those hits tends to be not
           | useful. As somebody mentioned below, being just a single
           | network hop away yields really low latency (~0.016ms in this
           | case) - that certainly helps being able to scale on little
           | hardware - typically only 10 - 20 concurrent requests would
           | be running in any instance at any one time because the
           | overall request end-to-end would take < 10ms to run.
           | 
           | Back in full framework days we had to do a fair bit of
           | optimisation to get great performance out of .NET, but as of
           | .NET Core 3.1 the framework _just gets out the way_ - most
           | memory dumps and profiling subsequent to that clearly
           | pinpoint problem areas in your own app rather than being
           | muddied by framework shennanigans.
           | 
           | Source: I used to work on the Platform Engineering team at
           | Stack Overflow :)
        
             | jorams wrote:
             | > cache hit ratio tends to be low
             | 
             | That's surprising to read. Is that because of the sheer
             | volume of question pages? I don't think I've ever been on
             | an SO page that couldn't have been served straight from
             | cache.
        
               | tomc1985 wrote:
               | Is it? Most people come to SO from Googling their random
               | tech problems/questions. Not sure how much value there is
               | in caching my random Rails questions, etc
        
               | setr wrote:
               | I would expect SO usage to follow a distribution like
               | Zipfs -- most visits hit a small subset of common Q/A,
               | and there's a ridiculously long tail of random questions
               | getting a few visits where caching would do next to
               | nothing. I'm fairly positive I've seen some post showing
               | this was true for atleast answer-point distributions.
               | 
               | Though I guess it's possible for a power distribution for
               | page-likely-to-be-hit to still be useless for caching,
               | because I think you could still get that distribution if
               | 99% of hits are on nearly-unique pages; with a long
               | enough tail, you'd still have only relatively few pages
               | worth bothering to cache, but by far most visits are in
               | the tail
        
             | sp33der89 wrote:
             | That's some great info, thank you!
        
           | foepys wrote:
           | > Honestly I have no idea how they do it on a .NET monolith
           | but there you go.
           | 
           | Low latency in a single rack can work wonders for
           | performance. All those cloud services talk to each other over
           | miles of cables and if you can slash latency to
           | submillisecond regions, you get less wait time and free
           | resources quicker. If you don't distribute your state across
           | multiple Microservices, you can also save quite a bit of
           | overhead.
           | 
           | Plus hardware is just wicked fast nowadays and SO has a model
           | of millions of reads for a single write.
        
           | orra wrote:
           | > Stack Overflow was running on .NET MVC on like 2 servers
           | pretty recently (with some auxiliary infrastructure for CDN
           | and search) and using MS SQL.
           | 
           | They are absolute _beasts_ of machines. But yes, it's
           | incredible what you can do with just a few colocated physical
           | servers.
           | 
           | It suggests to me lots of dev shops pay the IaaS or PaaS
           | cloud tax, long before they would have hit any scaleabilty
           | walls with a non-cloud setup.
        
             | danachow wrote:
             | A poster above claimed the servers were "48 logical cores
             | (2 x 12-core Xeons) and 64GB RAM", which really isn't what
             | I would consider such a "beast" of a machine when the RAM
             | is in laptop territory, and a modest number of cores for a
             | server.
        
               | smackeyacky wrote:
               | Nowdays you can purchase that machine on the second hand
               | market for something like $200-$300.
               | 
               | They are measurably faster than even contemporary laptops
               | though plus you often get ECC ram and raid disk setups
               | and the good old Xeon didn't used to ramp up and down in
               | speed, it just ran fast all the time. I'd still
               | characterise that as a beast, especially on $/performance
               | terms (although the power consumption is a worry).
        
               | toast0 wrote:
               | Xeon covers a pretty wide variety of chips. Of course,
               | the Pentium II Xeons didn't have speedstep either.
               | 12-core tells us either fairly high end but older or kind
               | of medium-low but newer. Dual socket tells us not the
               | really low end Xeon that shares a socket (and probably a
               | lot more) with the high end enthusiast desktop chips.
        
           | SideburnsOfDoom wrote:
           | > And anyway 99% of the time you're gonna be slow because the
           | sack of meat writing the program screwed up some aspect of
           | the system design or the code. Unless
           | 
           | Or in my experience, most of the time a service's latency is
           | dominated by out-of-process calls, e.g. the time taken to
           | talk to other services over http, or to retrieve data from a
           | data store. Speeding up the runtime is welcome, but even a
           | massive 40% speedup of something that constitutes 10% of your
           | total latency is ... closer to a 4% reduction in latency.
           | Design matters more.
        
             | emteycz wrote:
             | If your program is slow because it's waiting for external
             | service response, you're doing programming wrong. Your
             | program should do other work in the meantime. I guess
             | you're already doing that, but if so, doesn't that
             | invalidate your reply here?
        
               | SideburnsOfDoom wrote:
               | > you're doing programming wrong. Your program should do
               | other work in the meantime.
               | 
               | It's not always true that there is other work to do in
               | the meantime. In fact in my experience, it seldom is.
               | "you're doing programming wrong" is a very strong
               | statement, and not one that I take seriously in this
               | context.
               | 
               | Typically you "await" the external service response, so
               | that it is not using a thread to do that, and "other
               | work" in the form of starting to deal with other requests
               | can happen in the meantime, thereby increasing service
               | throughput.
               | 
               | But that won't speed up a given request - you can wait
               | for an external service more efficiently, but you can't
               | wait faster.
               | 
               | Services that do not depend on any other http services or
               | any data store do happen, but they are rare in my
               | experience (calculation engines, I suppose). So for
               | almost every service, when thinking about response time,
               | you have to, first and foremost, think about the latency
               | of the data stores or upstream services.
        
               | emteycz wrote:
               | That is all true, but in the context of .NET performance,
               | it's not relevant.
        
               | DeathArrow wrote:
               | >If your program is slow because it's waiting for
               | external service response, you're doing programming
               | wrong. Your program should do other work in the meantime.
               | 
               | What work? Mine bitcoins while you wait the result for an
               | API call?
        
               | emteycz wrote:
               | Usually processing other requests
        
               | atraac wrote:
               | I think any sane person here assumes any IO, especially
               | in .NET is already async and allows other requests to use
               | that time... Most web apps are still IO constrained.
        
           | DylanSp wrote:
           | Looks like SO's architecture is still pretty simple, yeah.
           | https://stackexchange.com/performance
        
         | txdv wrote:
         | .NET has the ability to handle your memory layout explicitly
         | with structs.
         | 
         | They expanded on that functionality with span and made sure
         | that the common libraries is implemented using this.
         | 
         | If you do textbook OOP development for everything, you will end
         | up with a lot of allocations and what not, which was the case,
         | so they went through the entire base class library and rewrote
         | all often used methods to be faster.
         | 
         | they even posted a bunch of posts with all their improvement
         | tricks: https://devblogs.microsoft.com/dotnet/performance-
         | improvemen...
        
           | DeathArrow wrote:
           | >If you do textbook OOP development for everything, you will
           | end up with a lot of allocations and what not, which was the
           | case, so they went through the entire base class library and
           | rewrote all often used methods to be faster.
           | 
           | They forgot to tell the others that there is life beyond OOP
           | and GoF design patterns.
        
             | mdoms wrote:
             | C# is filled to the brim with functional programming
             | features. Much of the base class library is somewhat
             | functional (although obviously not all or even most, given
             | the age of the BCL and stability of the API).
        
         | jayd16 wrote:
         | I assume temp solutions and low hanging fruit was added in the
         | move to .net core and the new compiler. Now that it's more
         | stable, things can get tightened up.
        
       ___________________________________________________________________
       (page generated 2021-11-21 23:00 UTC)