[HN Gopher] Performance Improvements in .NET 7
___________________________________________________________________
Performance Improvements in .NET 7
Author : mikece
Score : 196 points
Date : 2022-08-31 13:18 UTC (9 hours ago)
(HTM) web link (devblogs.microsoft.com)
(TXT) w3m dump (devblogs.microsoft.com)
| Mindless2112 wrote:
| > _try running Console.WriteLine((object)new uint[42] is int[]);,
| and you'll find it prints out True_
|
| I knew .NET's array variance rules were kinda bad, but that's
| really surprising.
| nimish wrote:
| Interesting that branch was chosen over CMOV in the ToString bool
| case, it's a PGO case study: https://discourse.llvm.org/t/rfc-
| cmov-vs-branch-optimization...
| rkagerer wrote:
| That blog site could use some performance enhancements. Anyone
| have a link to a static copy?
| mastax wrote:
| There was a (very long) post recently talking about the Regex
| performance improvements in .NET 7[0]. It's comprehensive and
| well written and I found it very interesting. I love the new
| Regex source generator not just because of the performance but
| because you can step into the C# code and understand pretty well
| what the regex is doing.
|
| [0]: https://devblogs.microsoft.com/dotnet/regular-expression-
| imp...
| hardware2win wrote:
| Damn
|
| Stephens posts exciting as always
| giancarlostoro wrote:
| Native AOT will come with .NET 7
|
| https://devblogs.microsoft.com/dotnet/performance_improvemen...
|
| > Native AOT is different. It's an evolution of CoreRT, which
| itself was an evolution of .NET Native, and it's entirely free of
| a JIT. The binary that results from publishing a build is a
| completely standalone executable in the target platform's
| platform-specific file format (e.g. COFF on Windows, ELF on
| Linux, Mach-O on macOS) with no external dependencies other than
| ones standard to that platform (e.g. libc). And it's entirely
| native: no IL in sight, no JIT, no nothing. All required code is
| compiled and/or linked in to the executable, including the same
| GC that's used with standard .NET apps and services, and a
| minimal runtime that provides services around threading and the
| like.
|
| Of course it does have some downsides:
|
| > It also brings limitations: no JIT means no dynamic loading of
| arbitrary assemblies (e.g. Assembly.LoadFile) and no reflection
| emit (e.g. DynamicMethod), everything compiled and linked in to
| the app means the more functionality that's used (or might be
| used) the larger is your deployment, etc. Even with those
| limitations, for a certain class of application, Native AOT is an
| incredibly exciting and welcome addition to .NET 7.
|
| I wonder how things like ASP .NET will run with Native AOT in the
| future.
| lvass wrote:
| I just can't help laughing profusely whenever I see MS doing a
| Native something. Don't you folks remember Native HTML5?
|
| https://www.youtube.com/watch?v=9mXe9nRiPHI
| SideburnsOfDoom wrote:
| > I wonder how things like ASP .NET will run with Native AOT in
| the future.
|
| Let me give an example of an ASP.NET app lifecycle: an instance
| is launched, goes through startup code once. When it reports
| itself healthy, it is put into the Load balancer and then
| starts handling requests. Code in these paths is executed
| anywhere from occasionally to 1000s of times per second. After
| around 24 hours of this, it is shut down and restarted
| automatically.
|
| So, compiler micro-optimising startup code to take ms off of
| it, is not interesting at all - it's only run once a day.
| Startup can take whole seconds, it makes little difference, the
| instance is ready when it's done. AOT in general isn't that
| important, but automatic tiered compilation based on usage data
| is very nice.
| trevorishere wrote:
| SharePoint, as an example, can take 1+ minutes to JIT.
| ewjt wrote:
| Serverless.
|
| Running an ASP.NET app in AWS Lambda is just a few lines of
| code. However, all of a sudden startup time becomes important
| for both performance and cost.
|
| These investments by Microsoft and others[1] allow .NET to
| remain relevant and viable for modern use cases.
|
| [1] https://github.com/awslabs/dotnet-nativeaot-labs
| SideburnsOfDoom wrote:
| Serverless is great, but if you want to go that route you
| should be aware that it is in no way a typical hosted
| ASP.NET app, and while you can "Run an ASP.NET app in AWS
| Lambda" with little code, there are are better ways to
| design a Lambda.
| ewjt wrote:
| Can you elaborate on "is in no way a typical hosted
| ASP.NET app"?
|
| I get that the machinery under the hood is different (ie.
| Kestrel web server may not get used). However, we
| typically don't care about those details. Our ASP.NET
| code runs in 3 separate places (containers, servers,
| Lambda) and the only difference between all 3 is a single
| entry point file.
|
| Do you mean because Lambda is only serving one request at
| a time and has a more ephemeral host process lifetime?
| SideburnsOfDoom wrote:
| > Lambda is only serving one request at a time and has a
| more ephemeral host process lifetime
|
| Yes, a typical hosted ASP.NET app is neither ephemeral or
| one request at a time. So this drives different design
| decisions.
| pjmlp wrote:
| Finally, I always though NGEN was a bad compromise and full AOT
| should have been supported since .NET 1.0, specially given
| Delphi's influence.
| ledgerdev wrote:
| It definitely will eventually, probably .net8 timeframe. It
| will be hard to support so many dynamic features and no doubt
| will make extensive use of Source Generators.
| https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/so...
|
| Anyone have any interest in a small c# aot micro web framework
| that cold starts up fast (~500ms, vs ~4s for non aot mvc) on
| serverless containers like google cloud run?
| geodel wrote:
| Good.
|
| Java is doing something similar with Graal Native Image thing.
| In a way it is funny to see few years back so many people were
| claiming that heavy CPU/memory usage of JIT based platforms
| would be even more non-issue in Cloud because one can scale as
| much they need on demand.
|
| And now I see AOT/Slimmed Runtime/Compact packaging are
| happening largely because of cloud deployments.
|
| Seems cloud bills are making impact in places where enterprise
| cloud architects were running amok with _everything micro
| service_ deployments.
| kevingadd wrote:
| I do extensive profiling of managed apps and while the JIT
| does eat a measurable amount of CPU time, it's really not
| much. And at least on .NET, you can manually ask the runtime
| to JIT methods, so you can go 'okay, it's startup time, I'm
| going to spin up a pool of threads and use them to JIT all my
| code' without blocking execution - for a game I'm working on
| it takes around 2 seconds to warm ~4000 methods while the
| other threads are loading textures and compiling shaders. At
| the end of that the CPU usage isn't a problem and you're
| mostly dealing with the memory used by your jitcode. I don't
| know how much of a problem jitcode memory usage actually is
| in production these days, but I can't imagine it would be
| that bad unless you're spinning up 64 entirely separate
| processes to handle work for some reason (in which case I
| would ask: Why? That's not how managed runtimes are meant to
| be used.)
|
| I mostly do JIT warming to avoid having 1-5ms pauses on first
| use of a complex method (which is something that could be
| addressed via an interpreter + background JIT if warming
| isn't feasible.)
|
| The slimmed runtime and compact packaging stuff is definitely
| attractive in terms of faster deploys and lower storage
| requirements, however, because the cost of needing to deploy
| 1gb+ worth of stuff to your machines multiple times a day is
| still a pain. I don't actually know if AOT is an improvement
| there though, since in some cases the IL that feeds the JIT
| can be smaller than the AOT output (especially if the AOT
| compiler is having to pre-generate lots of generic instances
| that may never get used.) You also have to ship debug
| information with AOT that the JIT could generate on demand
| instead.
| zeroc8 wrote:
| I 've never understood the point of JITing. Just compile
| the thing once for your target architecture and you're
| done. No more spawning threads for doing the same thing
| over and over again. I'm glad that languages like Go and
| Rust are bringing back the lost simplicity of yesteryear's
| dinosaur languages. Life can be so easy.
| carlhjerpe wrote:
| Reflection in C# is a thing, it isn't in either Go or
| Rust. I've read some kind of compiler shenanigans can get
| something that resembles reflection in C++.
|
| I love reflection, the fact that libraries can look at
| your types is really really cool.
|
| Not saying it can't be done with a compiled language but
| I don't see it anywhere.
|
| Being able to load a shared library, search it for
| classes implementing interfaces, instantiate them and
| call their methods is pretty slick too.
| pjmlp wrote:
| Go has reflection, and you can make use of compile time
| reflection on Rust via the macros infrastructure.
| carlhjerpe wrote:
| Does that cover all mentioned usecases though? They're
| discussing source generation in this thread, not even
| close to the same thing (for certain usecases)
| pjmlp wrote:
| Kind of, you can use the parsing package for that,
| alongside the //go:generate infrastructure.
|
| Or you can use Go reflection package and generate the
| source code from it.
|
| Of if wanting to do something like Assembly.Emit,
| generate the machine code directly with a little help
| from unsafe and syscall packages.
|
| Depends pretty much on the actual use case.
| pjmlp wrote:
| IBM OS/400 binaries (nowadays IBM i), can be executed in
| a completly different architecture from 1988, without any
| changes, possibly the source code doesn't exist anymore,
| while taking full advantage of IBM Power10 on its last
| iteration.
|
| Same applies to any other bytecode format making use of
| dynamic compilers.
| heurisko wrote:
| > And now I see AOT/Slimmed Runtime/Compact packaging are
| happening largely because of cloud deployments.
|
| I see the main driver of AOT to be startup time for things
| like lambdas.
|
| The JVM is pretty lightweight anyway on modern hardware,
| especially if you use modules.
| pjmlp wrote:
| Actually I think it is more competition pressure of languages
| like Go and Rust than anything else.
|
| I have been using Java and .NET languages for distributed
| computing for the last two decades, and JIT has always been
| good enough.
|
| By the way, Google rolled back their AOT compiler introduced
| on Android 5, and since Android 7 it uses a mix of highly
| optimized interpreter written in Assembly, a JIT compiler
| with PGO feedback, and when the device is idle, those PGO
| profiles are used to only AOT compiler the application flows
| that matter. On more recent Android versions, those PGO
| profiles are shared across devices via the Playstore.
|
| On the .NET front, I think the team has finally decided to
| make front of the whole C++ rulez of WinDev, specially after
| Singularity and Midori projects having failed to change their
| mind.
| [deleted]
| geodel wrote:
| Nowadays Go is working on a PGO solution, so there is that.
|
| I don't disagree but kinda doubt that new upstart languages
| with single digit market and mindshare in enterprise space
| would force .net /JVM behemoth to do anything. Forget Go,
| places I work would not know a single new thing beyond Java
| 1.7 or _latest Java 1.8_. But they have stood up a dozen
| _cloud teams_ doing every buzzword you can hear about
| cloud.
|
| So unless finance guys ask tough questions about rising
| Amazon billing IT wouldn't care if their SpringBoot crapola
| take 2GB of RAM or 32GB.
| pjmlp wrote:
| The new upstart languages are where the younger
| generations are, that is why you see .NET doing all those
| changes to make rolling an Hello World website as easy as
| doing it in Go, with global usings, single file code,
| simplified namespaces and naturally AOT.
| davidfowl wrote:
| We've been experimenting with NativeAOT for years with ASP.NET
| Core (which does runtime code generation all over the place).
| The most promising prototypes thus far are:
|
| - https://github.com/davidfowl/FasterActions -
| https://github.com/davidfowl/uController
|
| They are source generated version of what ASP.NET does today
| (in both MVC and minimal APIs). There are some ergonomic
| challenges with source generators that we'll likely be working
| through over the coming years so don't expect magic. Also its
| highly unlikely that ASP.NET Core will not depend on any form
| of reflection. Luckily, "statically described" reflection
| generally works fine with NativeAOT.
|
| Things like configuration binding, DI, Logging, MVC, JSON
| serialization all rely on some form of reflection today and it
| will be non-trivial to remove all of it but we can get pretty
| far with NativeAOT if we accept some of the constraints.
|
| As of right now, we're trying to make sure "motivated people"
| can play with it, but it's not something that is supported by
| ASP.NET Core or EF at the moment.
| https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+nativea...
|
| PS: Some of the challenges
| https://github.com/dotnet/aspnetcore/issues/42221
| jeremycarter wrote:
| Thanks for your hard work with the .NET community David.
| merb wrote:
| Actually system text json does work with source generators
| and di can work with source Generators aswell.
| davidfowl wrote:
| Thanks for telling me :). On a serious note though,
| anything can work with source generators but it doesn't
| match the style of coding that we'd like (moving everything
| to be declarative isn't the path we want to go down for
| certain APIs). Also source generators don't compose, so any
| source generation that we would want to use would need to
| take advantage of the JSON source generator (if we wanted
| to keep things NativeAOT safe). Right now most of the APIs
| you use in ASP.NET Core are imperative and source
| generators cannot change the callsite so you need to resort
| to method declarations and attributes everywhere.
|
| That's not an optimization, that's a programming model
| change.
| fabian2k wrote:
| I think typical ASP.NET applications likely won't use AOT in
| the near future. There is quite some "magic" in ASP.NET that I
| suspect won't work out of the box with AOT because it is
| heavily reflection-based. And while there are solutions for
| cases like JSON serialization, as far as I understand they
| require writing different code right now, so it's not
| automatic.
|
| AOT is much, much more interesting for cases where startup time
| matters, and ASP.NET usually isn't such a case. But I can
| imagine that it will be much more useful and easier to
| implement for smaller, focused tools that don't use that much
| reflection-based framework code. CLI tools might be the ideal
| case for trying this out.
| ewjt wrote:
| Serverless hosting (ie. AWS Lambda) makes ASP.NET a primary
| use case for AOT because cold startup times cripple
| performance and increase cost.
|
| I suspect they're just not ready yet and targeting the easy
| use cases (console apps).
| romanhn wrote:
| As someone writing a .NET-based API hosted on AWS Lambda, I
| assure you, startup time matters a ton. I spent a bunch of
| time getting cold start time down to a semi-reasonable
| number, but there's still a ton of room for improvement. I
| for one am very much looking forward to progress on AOT
| Native.
| fabian2k wrote:
| The "typical" in my comment was meant to take care of that
| part, I probably should have mentioned this explicitly. AWS
| Lambda is of course a case where startup time matters a
| lot, but it still leaves the common problem of ASP.NET that
| it was designed around a lot of reflection. My
| understanding is that this simply won't work with AOT out
| of the box unless you adapt all the places where you use
| reflection-based code. For example you'd need to use the
| source generator versions of JSON serialization and the EF
| Core DbContext in this case, with all limitations those
| have. But I'm not sure my understanding here is entirely
| correct or complete.
| paavohtl wrote:
| I don't know about ASP.NET, but the post says that
| Reflection.Emit is not available. Reflection.Emit is a
| namespace used for runtime code generation; I would
| assume most other parts of reflection are available, like
| with previous iterations of AOT support in .NET.
| kevingadd wrote:
| It is theoretically possible to have Reflection.Emit and
| DynamicMethod for less critical cases by using an
| interpreter - this happens in certain scenarios already.
| tmitchel2 wrote:
| I think you are correct. The DI container and JSON
| serialisation are two bigger areas that i suspect would
| need attention but as you say source generation solves
| the later and I think there is non reflection DI on the
| way if not already. I guess you would need to wait for
| any of the third party assemblies you depend on to allow
| for no reflection also...still a bit of a wait i think
| for my use case.
| ledgerdev wrote:
| The good news is that .net7 aot supports console apps so
| lamdas can already be native aot. Json serialization was a
| concern of mine, but it was surprising easy to get working
| with very minor changes in the call. If I were building
| lambdas would move it asap.
| tmitchel2 wrote:
| Lol snap
| fnord123 wrote:
| No, snap startups have an even worse startup time.
| SideburnsOfDoom wrote:
| As someone writing a .NET-based API hosted on AWS Lambda,
| your case is quite different to a "typical ASP.NET hosted
| application", that can run for days between restarts.
| ledgerdev wrote:
| I would like to host .net based api on google cloud run
| and azure container apps, which often will go to sleep
| after about 10 minutes without a request, so cold start
| time do matter quite a bit. I've done pretty extensive
| testing and see ~4-7 second cold starts with classic non
| aot mvc versus ~500ms with natively compiled golang/.net.
|
| The reality of the cloud is that sleep & cold starts are
| very common and in fact necessary to run efficient
| systems. Half a second is acceptable but 4+ seconds is
| not and so aot is very important for future apps.
| phillipcarter wrote:
| FWIW the problems with cold starts could also be solved at
| the platform layer. App startup is what typically dominates
| cold start times and there's creative ways to potentially
| frontload that, serialize the state, and treat all
| invocations as "warm".
| tmitchel2 wrote:
| Using ASP.NET with AWS Lambda or any other FAAS is a concrete
| scenerio. Startup time for that is critical.
| jackmott42 wrote:
| For people curious how much impact the .NET performance
| improvements over the last 5 years have on real, large scale web
| applications: At work we have a core piece of our online ordering
| system that has been running on .NET Framework 4.8. We run around
| 8 web servers and handle around 4,000 orders per minute, 300
| requests per second per server.
|
| We have been working on porting everything over to .NET 6 by
| making all the code compatible so we can build both from the same
| code base, and we just started putting the .NET 6 version live on
| one of the webservers for a few hours at a time to test it out.
|
| CPU usage on that .NET 6 machine is 1/2 of the Framework
| machines! Impressive improvement, and .NET 7 should be even
| better.
| pwdisswordfish0 wrote:
| "Framework" is such a poor differentiator to contrast with
| modern .NET (owing to the original poor naming decision in the
| first place--it's not like ".NET" itself is amazing) that it's
| hard, from a casual reading, to pick up on the fact that
| "Framework" is even being used a differentiator.
|
| I propose that when people want to differentiate between the
| modern .NET Core vs the legacy closed source .NET
| implementation, the latter is referred to as "OG" .NET (in
| casual and business-casual contexts, at least).
| wombarly wrote:
| Please, no more name changes.
| pwdisswordfish0 wrote:
| Not a name change, just an editorial prescription for
| discussions. The proper name is .NET Framework (just don't
| call it that!).
| branko_d wrote:
| IMHO, they should have just named the new one .CORE and
| called it a day.
|
| It would have made it immeasurably easier to google, and
| could have been be incorporated into other names to
| differentiate them from old versions: ASP.CORE, ADO.CORE,
| WinForms.CORE...
| copperx wrote:
| No, it's in their DNA to name things like that. "Windows"
| ... nuff said.
| jcpst wrote:
| Yes, it is terrible. I think you need to be an active .NET
| developer to communicate those subtle differences clearly.
|
| But we're used to it being bad at this point. .NET Framework,
| Microsoft Teams, Visual Studio Code...
| whoisthemachine wrote:
| A suggestion I liked was to call ".Net Framework" ".Net
| classic" a la "ASP classic", nicely honors the original .Net
| while properly suggesting it is not the "new" .Net.
| phillipcarter wrote:
| I've taken to calling it "Legacy .NET".
| na85 wrote:
| Microsoft is so incredibly bad at naming things it'd be
| hilarious if it wasn't so frustrating.
| whoisthemachine wrote:
| It feels like it _must_ be a company policy. When needing
| to compete with other major tools, choose a name so generic
| and so easily confused with other things that people who
| have no knowledge of the product will assume they need it.
| I can imagine some IT conversations 20 years ago along the
| lines of ".Net? I must need that for internet access!",
| just like I'm sure there are discussions today where
| managers assume they need Azure DevOps to get this new-
| fangled DevOps thing.
| XzAeRosho wrote:
| I don't follow the .NET ecosystem closely enough, but it feels
| that releasing a mayor version every year feels like kind of
| unnecessary? Or if they intend to keep doing this, they should
| release LTS versions of some kind.
|
| It feels kind of scary committing to .NET 7 right now, when in a
| year, it will be replaced by yet another major version promising
| ever increasing performance gains... Or is the difference between
| major versions not that big?
| bob1029 wrote:
| They do have a tick-tock-style LTS approach. Our strategy is to
| stick with the LTS versions, since we sell software to banks.
|
| The path we are on:
|
| Framework 4.x => .NET Core 2.x => .NET Core 3.1 => .NET 6 (we
| are here today) => .NET 8
|
| The migration from .NET Core 3.1 to .NET 6 was a total non-
| event. It was substantially harder for us to go from 2.x to
| 3.1.
|
| Based upon the current proposals and available documentation,
| we anticipate our migration from .NET6 => .NET8 will occur with
| absolutely zero ceremony sometime around Q2 2024.
| yodon wrote:
| Even numbered versions are LTS
| SideburnsOfDoom wrote:
| > they should release LTS versions of some kind.
|
| Uh? .NET 6 is the current LTS version. 8 will be the next.
|
| https://dotnet.microsoft.com/en-us/platform/support/policy
|
| I don't comment on Java or Python platform versioning policies
| because, like you with .NET, "I don't follow the ecosystem
| closely enough" so I don't have anything meaningful to say
| about it.
|
| > It feels kind of scary committing to .NET 7 right now .. Or
| is the difference between major versions not that big?
|
| Rolling forwards, the changes are very minor indeed. And there
| are utilities to automate parts of the update. e.g.
| https://dotnet.microsoft.com/en-us/platform/upgrade-assistan...
|
| There are of course new things that you will find missing if
| you're rolling backwards.
| TillE wrote:
| One of the weirder HN tropes is being upset that new software
| continues to be released, or that languages get updated with
| new features.
|
| I've so rarely seen truly major breaking changes that require
| substantial effort in updating your own code. Like, the
| Python 2->3 transition is notable because it's unusual.
| SideburnsOfDoom wrote:
| What I'm finding the weird trope is the pattern of: "I
| don't know anything about X, anyway why doesn't X do (thing
| that X has been doing for ages)"
|
| ignorance is no problem, I am ignorant of the details of
| most popular programming languages, and I know that. it's
| another thing to show awareness of ignorance, and then lose
| that awareness before the end of the paragraph.
|
| Whatever happened to "Whereof one cannot speak, thereof one
| must be silent."
| atraac wrote:
| > It feels kind of scary committing to .NET 7 right now, when
| in a year, it will be replaced by yet another major version
| promising ever increasing performance gains... Or is the
| difference between major versions not that big?
|
| Switching between major versions these days is incredibly easy
| so it's not like you pick a version for life. They're also not
| changing THAT much.
| ochronus wrote:
| They have an excellent track record of not breaking
| compatibility, most updates are drop-in & forget (unless you
| want to utilize new lang/runtime features)
| smcl wrote:
| I recall a few bumpy bits in the various upgrades from 1.0 to
| 2.2 - they reworked quite a few areas such that updating the
| .NET Core version required changing your code. They provided
| good documentation and migration guides, but they did
| definitely break things along the way.
| ThunderSizzle wrote:
| I recall most developers didn't jump from 472 to core 1
| since this was thr expectation.
|
| I barely started touching core until core 3, and really
| started checking out .net 5.
| smcl wrote:
| To be honest we didn't migrate .NET Framework apps - new
| build was done in .NET Core and thankfully there were a
| few smaller projects in the pipeline to allow us to
| fiddle with a bit through the transition 'til it was a
| bit more stable.
| quaffapint wrote:
| .NET Core 3.1 and .NET 6 are LTS (though 3.1 ends this year).
| Also in general things don't break that much. There are cases
| like nullable checks whose default changes and so if you go
| with that default you will have to update, but it's tweaks more
| than overhauls.
| kryptiskt wrote:
| Every other release is an LTS release, with three years of
| support. .NET 6 was one so this won't be.
|
| They are pretty good about backwards compatibility, upgrading
| .NET Core and .NET hasn't been a big deal so far.
| mikece wrote:
| I have an issue with calling three years "long term" support.
| Most companies won't update to the new LTS for 9 to 12 months
| in order for any issues to be ironed out, so that means you
| get only 24 to 27 months on the LTS. Between CVEs and
| upgrading to dotnet6 before the end of life on dotnet3.1 most
| of my coworkers and I have gotten almost no new coding done
| on our applications this summer (and this was after a three
| month blitz to get all of our code up to dotnet3.1 ahead of
| the dotnet2.1 end of life less than a year ago). As long as
| the LTS doesn't introduce a lot of breaking changes then it's
| not that big of a deal but when you have to refactor and
| rewrite non-trivial chunks of code this gets to be really
| wasteful.
| guhidalg wrote:
| What did you have to rewrite when upgrading from .NET 3.1
| to 6? If all you had to touch was ASP.NET startup changes,
| that's hardly 1 day's worth of work.
| danparsonson wrote:
| I have to agree that it's excessive and I don't understand why
| they're doing it. Major versions imply breaking changes, which
| contradicts the assertions of other people here replying that
| the differences between each version are minor; in that case
| why not minor version bumps? What's the benefit? The only thing
| I can think of is that it forces upgrades to new versions of
| Visual Studio.
|
| One immediate problem it creates is with recruitment - between
| 2019 and 2021 we went from .NET Core 3.0, through 3.1, .NET 5,
| and now .NET 6, and suddenly in the space of one job I went
| from up-to-date to 'legacy CV'.
| ewjt wrote:
| The annual cadence simplifies our planning-- we can preview
| features a year ahead and prepare for the LTS release. It
| also shortens the feedback cycle for Microsoft which has to
| be useful.
|
| From a recruiting standpoint, it allows me to start
| conversations. I don't take points off if candidates haven't
| worked on the latest version, but one of my go-to questions
| is "What features in .NET X are you looking forward to
| using?".
|
| In an industry of constant change, it's a negative signal if
| you don't know _anything_ about the current version of the
| platforms you use. Many, many candidates don't.
| ahtihn wrote:
| Why would you list the .NET version on your CV? Why would
| anyone hiring care about whether you have experience with
| .NET 6 vs .NET 3
|
| Do you also list all the library versions you've worked with?
|
| This is pretty absurd.
| danparsonson wrote:
| The .NET framework has changed a great deal between
| versions 1 and 6, so I don't agree that it's sufficient
| just to say that I am experienced with .NET and leave it at
| that, nor is it equivalent to listing library versions.
| Besides I'm a contractor; potential customers are usually
| looking for someone who can hit the ground running, not
| spend a month skilling up.
| nightski wrote:
| If a recruiter denies you because you have .NET 6 on your
| resume instead of .NET 7 then that probably isn't a very
| lucrative job in the first place. You don't need a month
| of skill up to go from 6 to 7, maybe like 10 minutes.
|
| Personally I'd just say .NET in general and leave the
| specifics to the interview.
| ewjt wrote:
| It's a minor signal, but it's still a signal.
|
| If someone only lists "Angular", it could be Angular 4 from
| 2016 or something more relevant.
|
| Same thing with .NET-- the version can imply Windows-
| related experience (.NET Framework) vs. something more
| cloud native (.NET 6).
| Salgat wrote:
| Major versions do include breaking changes in some libraries.
| You usually keep all Microsoft libraries aligned on the same
| major version to ensure compatibility, and it allows
| Microsoft to introduce these breaking changes on a regular
| basis without causing any confusion. If you're on .NET 6,
| most of your Microsoft nugets are on 6.xx.xx.
| ThunderSizzle wrote:
| It gets really weird when you have one dependency including
| .NET 6 version, and another including .NET 5, since they
| sometimes rework nuget packages with how many
| Microsoft.Extensions they have now.
| cyral wrote:
| The updates from .NET Core 2 to .NET Core 6 have taken me maybe
| an hour of combined work across many years. Each major version
| has barely any breaking changes if any.
| Wohlf wrote:
| Yeah it's pretty much just new features, and you can stick to
| the LTS releases.
| fabian2k wrote:
| The most recent upgrades were pretty easy, it looks like the
| more disruptive changes are mostly done now.
| phillipcarter wrote:
| > Or if they intend to keep doing this, they should release LTS
| versions of some kind.
|
| That's exactly what they do: https://dotnet.microsoft.com/en-
| us/platform/support/policy/d...
| esprehn wrote:
| Unfortunately looks like still no compact strings like Java or
| JS: https://github.com/dotnet/runtime/issues/6612
|
| You can work around it, but it's nice in languages where common
| text doesn't take double the memory (because of utf8 or compact
| strings).
| svick wrote:
| UTF-8 string literals will be part of C# 11/.Net 7, which could
| help. But they're still more awkward to use than the UTF-16
| string.
| gavinray wrote:
| Is this what you're talking about? > "Arguably
| the biggest improvement around UTF8 in .NET 7 is the new C# 11
| support for UTF8 literals." > "UTF8 literals enables
| the compiler to perform the UTF8 encoding into bytes at
| compile-time. Rather than writing a normal string, e.g.
| "hello", a developer simply appends the new u8 suffix onto the
| string literal, e.g. "hello"u8. At that point, this is no
| longer a string. Rather, the natural type of this expression is
| a ReadOnlySpan<byte>. If you write:" > public static
| ReadOnlySpan<byte> Text => "hello"u8; > public
| static ReadOnlySpan<byte> Text => new
| ReadOnlySpan<byte>(new byte[] { (byte)'h', (byte)'e',
| (byte)'l', (byte)'l', (byte)'o', (byte)'\0' }, 0, 5);
| esprehn wrote:
| No, not unless you can pass a ReadOnlySpan into every API
| that expects a String. The change you referenced let's folks
| work around the fact that String is UTF16. It doesn't
| transparently handle ASCII with one byte like other
| languages.
|
| See the GitHub issue or https://openjdk.org/jeps/254
|
| The .NET 7 change doesn't retain backwards compatibility
| [deleted]
| spaetzleesser wrote:
| On the one hand it's cool that they are improving but how do
| people keep up with all these additions? I find this really hard.
|
| Seems a lot of the changes are new stuff which you have to
| evaluate and see how they could actually be used productively.
| For example a while ago I tried the new nullable stuff and while
| in theory it looks straightforward it turned out to be very
| difficult to use nullable with existing APIs and code in a
| productive way. The same applies to a lot of the other new
| features.
|
| I feel .NET Core after a good start is falling into the typical
| Microsoft trap of constantly cranking out new stuff to do the
| same thing and leaving it to developers to keep up. That's how we
| ended up with several .NET desktop UI frameworks that are more or
| less in maintenance mode without a real upgrade path to the
| currently fashionable framework (which will most likely be
| abandoned soon too).
| MarkSweep wrote:
| A lot of these things you will get the benefit from upgrading.
| Also see the last section of the post about analyzers. You can
| enable these and Visual Studio will identify and potentially
| automatic improve performance by using different APIs.
|
| There are a performance ton knobs you can turn both at develop
| time and deployment time. There are 4 ways to run Regexes in
| .NET 7! (Interpreted, compiled, the new non-backtracking
| interpreter, the new compile time source generator). I do agree
| with the assessment that it's hard to keep up with.
| bestinterest wrote:
| I very much like the ethos of Golang for this reason. Still not
| had a reason to use it but like the idea of mastering the
| fundamentals in a weekend. Even if I lose the flexibility of
| LINQ or Java streams.
|
| It feels like a scale of language conservativeness Go all the
| way at the top, Java somewhat in the middle (a little above)
| and C# at the bottom. It is going the route with lots of
| features and complexity, which can be a great thing but not for
| grug devs https://grugbrain.dev like me.
|
| But saying all that Blazor looks really good for WebDev, I just
| worry it gets abandoned. It feels everything does in the C#
| space.
|
| C# also made a big mistake imo by going with async/await
| instead of lightweight threads which will add a ton of
| complexity in the future for if they decide to go the
| greenthread route like Goroutines/Project Loom.
| whoisthemachine wrote:
| > C# also made a big mistake imo by going with async/await
| instead of lightweight threads which will add a ton of
| complexity in the future for if they decide to go the
| greenthread route like Goroutines/Project Loom.
|
| Could you expand on this? Async/await is just syntax magic
| for Task continuations (in other words, Promises [0]), which
| have very little to do with the underlying threading model.
| This statement is equivalent to saying "Completable Futures
| add a ton of complexity to Project Loom."
|
| [0] https://en.wikipedia.org/wiki/Futures_and_promises#List_o
| f_i...
| bestinterest wrote:
| I think this post has the best information on it as I am
| also learning here
| https://journal.stuffwithstuff.com/2015/02/01/what-color-
| is-...
|
| It is not just `magic` syntax imo, it is viral to your
| codebase. The blog post does way more justice than I can
| explain.
| whoisthemachine wrote:
| Yes I understand the function coloring "problem" (oh no
| functions need to specify in their signature whether they
| return results immediately or eventually). Regardless, I
| still don't understand how this prevents green threads a
| la Project Loom, if you have a function that returns a
| `CompletableFuture` in Java, it also needs to change its
| signature.
| metaltyphoon wrote:
| For what it's worth, there is experimentation of green
| thread in C# happening.
| blackoil wrote:
| IIRC, the statement was from some Java blog about Loom.
| Idea is that with lightweight threads you can make
| everything sync and still be performant. While C# has gone
| ahead with making everything async
| whoisthemachine wrote:
| I understand the difference in approaches. However, the
| parent stated that this decision makes green threads
| harder in C#, which is what I don't understand.
| keltex wrote:
| > But saying all that Blazor looks really good for WebDev, I
| just worry it gets abandoned. It feels everything does in the
| C# space.
|
| I've been maintaining a asp.net (WebForms!) framework
| codebase for almost 18 years now. Running on the latest
| Windows Server and Visual Studio 2022.
| rr888 wrote:
| I think this is pretty common with a lot of legacy code bases
| in popular languages. Lots of big systems on Java 8, Python 2,
| we wont talk about JS. :)
| francisofascii wrote:
| Fortunately the upgrade path has not been too bad once you get
| to .NET Core. Usually one time changes to your Program.cs and
| Startup.cs files. The Top-Level statements addition is pretty
| jarring at first, but a cool addition. I did run into a
| breaking change from .NET 5 to 6 with an Encryption library not
| working right. But most everything else just works when
| upgrading. If it was just .NET additions life would be fine. It
| is the front-end churn that causes real stress. AngularJS,
| TypeScript, Angular, React, Blazor, WebPack, Vite, etc.
| hardware2win wrote:
| >On the one hand it's cool that they are improving but how do
| people keep up with all these additions? I find this really
| hard.
|
| Very often they improve things in a way that you'll get an
| improvement regardless of whether you are aware
|
| E.g linq, collections, regexes, etc.
| bob1029 wrote:
| I don't try to keep up with absolutely everything. I've been to
| this particular buffet for a really long time and have
| developed tastes for certain things.
|
| For instance, I recognize AOT is elegant in theory, but I also
| notice it's a difficult thing to get right and has certain
| tradeoffs. Especially, for a complex application that may need
| to use legacy APIs. As a consequence, I have mostly avoided
| this in favor of focusing on other areas that do seem to
| deliver additional value for our product (and my side-
| projects). Examples of these being intrinsics (SIMD), UTF8
| text/serializer, file I/O and more advanced GC techniques.
|
| Ultimately, it's a matter of experience to know when you should
| and should not chase a particular rabbit. My general policy
| right now is to observe the new shiny while it's in the odd-
| version, and then wait to see how it shakes down by the time
| the LTS comes around. You almost never want to try to grab a
| Microsoft-branded rabbit upon the very first sighting.
| vsareto wrote:
| Bookmark https://devblogs.microsoft.com/dotnet/ and read
| occasionally. https://docs.microsoft.com/en-
| us/dotnet/csharp/whats-new/csh... is good for a quick overview
| of language features depending on what version you're at.
|
| Most .NET devs only need to be peripherally aware of these
| changes, as most businesses using .NET will move slower than
| Core's new pacing. It's even less important for lower seniority
| devs as you typically need project changes to utilize new
| features, which is a call a senior would make, which involves
| approval/testing/deployment, so a slow process which gives you
| time to read up on the new features as they're needed.
|
| You're better at your "craft" the more tools you know about and
| how to apply them, but if your day job prevents you from
| following the new stuff, I wouldn't worry too much about it.
|
| >I feel .NET Core after a good start is falling into the
| typical Microsoft trap of constantly cranking out new stuff to
| do the same thing and leaving it to developers to keep up.
|
| Yeah, the pacing has increasing dramatically from .NET
| Framework days, but that's probably a good thing. I would just
| stick to learning about what you do in your day job. .NET has a
| huge ecosystem compared to other languages, so it's going to be
| very hard to keep up with everything MAUI is doing if you're
| doing regular ASP.NET core APIs.
| pjmlp wrote:
| We don't really keep up.
|
| I read with interest all these articles, and then go back
| coding our LOB stuff in .NET Framework 4.7.2 and similar.
|
| On the Java side, I am finally confident that all our servers
| have at least Java 11 on them.
|
| Only on private stuff do I happen to enjoy latest versions.
| kevingadd wrote:
| You really don't need to use any new features to get the
| benefit of improvements in many cases, because the standard
| library is updated to use them. So things like string and array
| operations just get faster.
|
| I've started using 'ref readonly' and stuff like that in bits
| and pieces of my application code, but the rest of it is
| basically written in a .NET 4.0 style and it's fine, there's no
| obligation to use the new stuff unless you want to. I've
| started using some of the newer syntax sugar to make things
| more concise, like local functions, value tuples, and short
| property definitions - but again that's totally optional.
| jabart wrote:
| Nullable's have been around for at least a decade and before
| .Net core existed? Are you thinking of the NotNull attribute
| argument checking instead(Likely the wrong term here)? Any
| change in a data type to an existing API or code will always be
| tough and a lot of work. Maybe an in32 to a in64 being the
| exception.
|
| Library developers are looking at these and following them to
| make enhancements. Developers working on business apps get the
| automatic performance improvements of these changes and the
| library dev changes to improve performance and allocations. I
| personally quickly go over these so when I get into a
| performance issue I have a little bit to know where to go find
| more information.
| nightski wrote:
| Pretty sure they mean Nullable reference types which are much
| newer (although they have been around for a while at this
| point).
| ewjt wrote:
| Can you name other development platforms of similar scale/depth
| that don't have this issue?
|
| Compared to the whirring treadmill of frontend web development,
| I find .NET to be pretty easy to keep up with. Good IDEs
| (ReSharper or Rider) really help with the new language features
| (which are opt-in).
|
| Outside of that, the ecosystem is large enough that there are
| quality blogs/articles/podcasts to stay current without sinking
| a ton of time into doing so.
| asdajksah2123 wrote:
| Front end development may have a lot of frameworks, etc., but
| so much less magic than .Net.
|
| What makes .Net so much harder (especially ASP.Net) are the
| new features but also all the magic that makes
| discoverability so hard.
|
| Front end frameworks tend to follow similar patterns, and
| where they differ, they usually advertise the difference
| between the standards heavily.
|
| But also, since they are genuinely different frameworks, it's
| easier to search the differences etc. So, if I open a Vue
| application codebase, I know almost immediately that it's a
| Vue application and not a React one. I can google vue and
| figure out (most likely from their getting started page)
| exactly all I need to know to get started.
|
| If I enter an ASP.Net codebase, on the other hand, I have no
| idea whether I'm looking at ASP.Net Pages, .Net WebAPI, .Net
| WebServices, or more often than not, some combination of all
| of them. Throw in some Dependency Injection, with a
| combination of IOC containers used in the same project, and
| it's a massive lift to know what even to Google for.
| metaltyphoon wrote:
| I hear this word all the time "magic". Can you describe
| what it means with concrete example for other stacks?
| ewjt wrote:
| Magic means "hidden complexity", AKA "abstraction". The
| negative connotation is that sometimes you can't figure
| out why your software is behaving a certain way and what
| you need to do about it.
|
| The positive connotation is that you write less code with
| less cognitive overhead.
|
| Generally I prefer ASP.NET over things like Spring and
| Ruby on Rails because it has less magic, despite being
| clearly inspired by both of those.
|
| Here's a concrete ASP.NET example: You can put an
| [ApiController] attribute on your controllers and it can
| change the structure of error responses, among other
| things. [1]
|
| I don't agree with some of the other parent points. For
| example, the comments on "multiple dependency injection
| container" --- ASP.NET is pretty prescriptive on DI
| patterns. That sounds like someone made a decision to add
| complexity, which is on them.
|
| [1] https://stackoverflow.com/a/66546105
| metaltyphoon wrote:
| So "non magic" means to write everything then? Because
| the example you showed you have to understand a language
| feature, attributes. Then see the source code, which is
| open, and how it's being used.
|
| So, are Rust macros, or C macros, C++ templating magic or
| it's just means "I don't want to know how this works
| therefore it's magic"?
| cerved wrote:
| Http request handling in asp.net mvc. The uri, type and
| parameter serialization is a magic mess.
|
| How do you PUT { "foo" : { "bar" : "baz" }} to
| ping/pong/yolo?
|
| You create a controller class, PingController, you create
| a method PutPong, then you give up and proceed to cry
| blood
| aliswe wrote:
| something like
|
| app.MapPut("ping/pong/yolo", ctx => ...);
|
| and in there you read the Body as string ... it should be
| a one liner?
| guhidalg wrote:
| It seems you had a bad time learning ASP.NET, but in my
| experience what you're asking for is not difficult at
| all.
|
| You have to: 1. [Optional] Define a DTO that deserializes
| { "foo" : { "bar" : "baz" }} to an object 2. Write a
| class that subclasses Controller 3. Write a method, call
| it whatever you want, that accepts a JObject or one of
| your DTO types. 4. Add the attribute
| [HttpPut("ping/pong/yolo")] to tell the framework this
| method should be bound to PUTs for that path. 5. Write
| your business logic.
|
| Is that blood-crying inducing? No.
| fabian2k wrote:
| https://devblogs.microsoft.com/dotnet/performance_improvemen...
|
| This is a really interesting, or rather terrifying part of that
| blog post. I thought I had a reasonably good knowledge about
| typical performance mistakes in .NET, but I never heard about
| this particular one.
|
| If I understand it right, initializing a fresh
| JsonSerializerOptions object before each call to
| Serialize/Deserialize in System.Text.Json is incredibly
| expensive. It essentially disables the cache and means the
| serializer analyzes this case fully every time. And this is more
| on the order of 100x as expensive than using the cached version,
| so not a trivial amount.
| AtNightWeCode wrote:
| Yeah, it should be in a static property/field or a singleton.
| Seen measurable improvements based on fixing this.
| System.Text.Json really has many unnecessary pitfalls. Maybe
| they should have fixed the memory problems with Newtonsoft
| instead. A much more practical lib.
|
| Edit: With that said, in most apps JSON speed is very not
| important. Never seen it consumed more than couple of percent
| of execution time for APIs since .NET 1.1.
| jayd16 wrote:
| Newtonsoft isn't AOT friendly though. That's why they went
| with both.
| AtNightWeCode wrote:
| AOT? I really don't understand why they made the transition
| to System.Text.Json impossible for most projects.
| kevingadd wrote:
| A polite way to describe most serialization tooling in the .NET
| ecosystem would be "bad". It's unfortunate, but it's good to
| see improvements happening. I still try to avoid JSON in
| general on .NET since I've had so many bad experiences with the
| various JSON libraries out there.
|
| Sadly if you want to ship well-performing software in .NET it's
| still mandatory to run it under a profiler on a regular basis,
| both to spot frequent unnecessary GC allocations and to spot
| CPU bottlenecks. Either one would probably catch this
| particular problem, thankfully!
|
| I use the built in VS profilers sometimes, and other times I
| use Superluminal's excellent CPU profiling.
| aliswe wrote:
| Streaming serialization with System.Text.Json doe.
| krona wrote:
| I wish benchmarks with sample means in the tens of nanoseconds
| weren't reported and compared by the arithmetic mean. These are
| not normal distributions and a 10% improvement could just mean
| you improved the 99% percentile, which is quite typical in my
| experience given how skewed the distributions tend to be.
| uwuemu wrote:
| ... that awkward moment when video game tech reviewers like
| DigitalFoundry provide better benchmarks of video game
| performance than a tiny company like Microsoft does for its
| biggest inhouse programming ecosystem.
| kevingadd wrote:
| Video game performance is generally measured in milliseconds,
| not nanoseconds. The comparison would be if you were
| benchmarking things like physics sim updates on a per-object
| basis, or rendering on a per-triangle basis. Those would also
| be in nanoseconds.
|
| As a game dev you're typically operating in terms of things
| like 'rendering our UI is taking 0.5ms, can we get it lower
| so we have more time for the terrain?'
| svick wrote:
| Many of the benchmarks are using BenchmarkDotNet, so consider
| reporting this to them:
| https://github.com/dotnet/BenchmarkDotNet/.
| hermitdev wrote:
| Looks like the author is explicitly excluding "Error",
| "StdDev", "Median", "RatioSD" from the ouput. It's in the
| setup[0]. I'm guessing the author omitted them for brevity.
|
| [0] https://devblogs.microsoft.com/dotnet/performance_improve
| men...
|
| edit: meant "excluding", not "including"
| devmunchies wrote:
| > A huge amount of effort in .NET 7 went into making code gen for
| Arm64 as good or better than its x64 counterpart
|
| Awesome. I was using an LSP server for F# (in Sublime Text) on an
| M2 Mac and it was always running at 500%+ CPU. I had to turn off
| the LSP server. Hopefully this version fixes it.
| chusk3 wrote:
| Assuming you're talking about FsAutoComplete and this was
| recently, that's nothing to do with the .NET Runtime and
| entirely a coding mistake that I made that we've released a fix
| for :)
| noveltyaccount wrote:
| This is the most Hacker News comment I have ever seen, lol.
| The actual guy behind the bug here replying to comments with
| a mea culpa :D
| devmunchies wrote:
| Oh! HAHA it was FsAutoComplete. right on. Thank you!
___________________________________________________________________
(page generated 2022-08-31 23:02 UTC)