NativeAOT is one of the most important feature C# needed, very nice that it is finally coming, i still can't believe it took them this long
Congrats to everyone who fought vigorously to make it happen, screw the managers, execs and their surrounding noise, long live to the real engineers at Microsoft
This was the first thing I tried out this morning and apparently it is not meant to work with ASP.NET (Web API in this case) and only for console applications.
Explains why my container got stuck packaging Kestrel this morning.
- "All required code is compiled and/or linked into the executable, ..."
- "No JIT means no dynamic loading of arbitrary assemblies ..."
- "... with everything compiled and linked into the app ..."
This sounds very much like static linking, possibly with no option of dynamic linking/loading of code.
Presumably this would have implications for those using LGPL-licensed .NET libraries, especially those who'd like to distributed closed-source applications AOT-compiled using this approach?
Are there any commonly-used .NET libraries these days that are only LGPL-licensed?
I haven't done .NET development in a decade, so I don't really know the current state of affairs.
I don't think that conflicts with what I said. You have to be able to replace the library and them shipping linkable objects does that. Most static releases do not do this.
Yes. Because dynamic linking happens at runtime, the DLL/so file can be replaced by a downstream user. Static linking does not allow the user access to that "freedom", so the whole binary becomes "infected" and must be open sourced. By enforcing a "user replaceable" boundary, the users' freedoms/rights to modify the open-source library are unaffected.
Side note: how does that fit in with cryptographic signatures? GPL v3 was written to combat "Tivoization" (open source, but can't replace the binary). Does the LGPL v3 disallow such things with DLL/so files (use hashes to prevent replacing the FOSS lib)?
Straight from the LGPLv3: "A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version."
The LGPL's boundary between your application and the licensed library requires that the end user have some way of substituting the LGPL library. So if your project is not at least source-available enough for the end user to recompile it with a modified version of the LGPL library, you're going to have a hard time meeting that requirement with static linking. More common is to just dynamically link to the LGPL library, which provides the substitution mechanism by its very nature.
I have used NativeAOT before, and it does not enforce static linking. "no dynamic loading of arbitrary assemblies" refers to .NET assemblies, not the native dynamic link libraries they are compiled (using NativeAOT) to
They really need to extend the support time for their LTS releases. Sure, if you're developing a SaaS you can stay on top of .NET versions but it's definitely causing friction for enterprise and slow moving regulated software. .NET Framework 4.5.2 was supported for 8 years in comparison.
We're about to start a project with those limitations and there really is no good choice now that .NET 6 is already a year through it's lifecycle.
If, when publishing your app, you choose the "self-contained" mode (as opposed to "framework dependent")[a], the runtime will be bundled with your program into the executable. Then you don't need to worry about updating your client's OS. My work is using it for deployment to Linux, and it works great.
Seems like it makes the problem worse because you are then tied to a specific version at time of publishing and need to republish to get any framework patches.
Indeed. Microsoft identified this as a problem as well and pushes .NET security patches via Windows Update nowadays. When using self-contained apps, you won't get these patches.
You missed how there effectively isn't a .NET Core/.NET Framework delination anymore. It is just .NET, and .NET gets security patches from Windows Update.
> Sure, if you're developing a SaaS you can stay on top of .NET versions but it's definitely causing friction for enterprise and slow moving regulated software.
You have a point, but I'd call out that migrating to newer releases can and often is trouble-free.
A couple of months ago I worked on a .NET Core 2 web service that was put on cold storage for a few years, and all it took to migrate it to .NET Core 6 was a few version number bumps and a rebuilding the project.
YMMV of course, but LTS shelf life might not be a deal breaker.
It took almost two years of development to do this conversions in out project... but in my case heavy lift of move from webforms to mvc were already done, so it a bit easier.
Unfortunately in some industries continuous delivery is literally illegal. Anyway there's a real issue with their current schedules. Let's say you're developing software some time in the middle of next year. There's effectively no LTS release available at all.
We're not talking about "continuous delivery", this is just having a plan to ship updates every two years, on a well defined schedule. If you can't manage that organizationally, there are deeper problems.
It's not really Microsoft's job to work around your awkward requirements. Everything is open source, you can ship patches for .NET 6 yourself if you really want to.
My issue is the cadences are difficult to work with.
Microsoft's general-ish LTS for .NET is 2 years. We also only seem to get a new release every 2 years. It's hard to handle breaking changes between two versions quickly.
Node (used at least as much as .NET and Java in enterprise) has a 3 year LTS cycle
I'm gonna need a citation on that. From what I've seen, what enterprises have done any node adoption have fled it like rats fleeing a sinking ship because of all the problems it's had over the past half decade. To the point that shops I've worked with are moving back to Java.
I agree that LTS should last longer. They made it easier to upgrade between versions though. Perhaps won't help you if you use .NET in patient critical medtech for instance (in EU).
Biggest problem for us is .NET Standard. I don't even understand how it could work on a theoretical level. Maybe it could work if there was no dependencies.
I know what it is. It is just broken. App A uses a .NET Standard lib B that needs lib C. Since the purpose of lib B is to be as compliant as possible it targets some .NET Standard 1.x. Lib C is used already by the app. And now, dependency hell.
I guess I am missing something, why does this cause dependency hell? I guess microsoft is basically recommending against targeting netstandard now anyways so there must be some problem with it. But I don't think I have run into any problems with the situation you described.
edit: Ok I see, it seems in that scenario loading the correct assembly is more difficult on dotnet framework and usually requires binding redirects to be specified. On dotnet core/.NET 5+ there are no issues though, which is why I haven't experienced this problem myself.
What limitations are involved? I’ve never really understood why 3 years is unacceptable or intractable. In nearly every case the real issue is that nobody wants to fix broken internal processes that prevent people from upgrading once a decade.
It has everything to do with creating a product that you sell to a customer who installs it on premise within their environment, and their IT policies require that software be supported for a certain period of time. Even if you're good at changing their mind some of the time, it's not going to happen every time, so you're basically turning away potential customers, which some people aren't willing to do.
This is why it's much better to move away from the shrink-wrap model of delivering software and focus on SaaS only solutions.
It's not always that the internal process is broken - it's that sometimes it takes a very long time to get a new release approved for use (even if it's an upgrade to one that the customer has already been using). Sometimes it's the customer's process that is slow (big enterprise culture), sometimes there are one or more third parties involved. Sometimes it's both.
Many years ago I wrote software for a medical device. Before we could sell the device we needed to get it tested by Underwriters Laboratories to ensure it was safe (wouldn't shock people) and could be cleaned by hospital staff without damage. We also had to do the process to get the CE mark for it so it could be sold in the EU. And of course the FDA needed to approve it. It took nearly a year for all this, before we could offer it for sale and start marketing it.
So there's a third of the LTS lifetime consumed, right there.
There isn't any functional difference between a 3 year or 5 year or 8 year support cycle. The only two development modes for a service are – build once and maintain occasionally, or build once and leave untouched forever. Those in the first set will be fine with 3 years of support. Those in the second will always ask for more time no matter what the deadline is.
There will be a new LTS version available for 1 out of those 1.5 years. Plenty of time to upgrade. Plus, the advantage of shorter release cycles is that there are fewer breaking changes from one version to next. As long as there is decent test coverage it could be as simple as updating the build target in your CI tooling and calling it a day.
We're in the process of migration a large MVC application from Framework 4.8 to .NET 6. It's been....painful. Hopefully at least for a while updating to new LTS versions will be less so.
We did that last year on a 3 million line / 500 person-year investment application. Quite challenging as everything from app domains to remoting, to call contexts and other unsupported things were being used. It was definitely worth it for performance alone as we were also using Mono to run on Linux.
I am moving a personal project with ~50k loc and it has turned into a rewrite of about 2/3 of it. Not fun, but on the plus side the app runs A LOT faster now. So much faster that even non tech people that use it noticed the difference.
I love Java. And I'm working on c# right now at my job and I'm loving it too. This is happy news for me. When my enterprise finally adopts it 4 years from now. D:
Upgrades are honestly really easy, and have been since around .NET Core 2.
I have now done 2 -> 2.1 -> 2.2 -> 3 -> 3.1 -> 5 -> 6 with very little friction at all, in a fairly big web API codebase.
I don't foresee any issues going from 6 -> 7. 5 -> 6 was essentially just a find and replace on TargetFramework and it all just worked.
Ahh. I think it was quite an effort. The whole organisation really did spend some time and tested it thoroughly. I reckon it depends on the scale and complexity of the code base. I'm not a dev, I don't know enough. I'm worried about changes to Python packages breaking my code. haha.
Seems like the only reasons for upgrading from 6 to 7 would be an easier path (possibly) to upgrade later than going from 6 to 8, or if you really want to use something in c# 11 (https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...) . I remain unconvinced...
If you are using `time` and calculate the time from application startup to exit 0 then it is not representative of performance of the code itself - more aggressive optimization in JIT tend to have increasing cost with each release even if the people working on it try to always ensure the compilation throughput stays constant and we get more optimized JIT code per same amount of CPU work.
If you would like to have representative benchmark data, I suggest relying on BenchmarkDotNet instead.
Looking further into it (I really want my program to run faster!), looks like 7 produces unoptimized code. Could it be that it decided for me that I want faster startup vs faster code? Can I force it to turn optimizations on somehow?
If you do only a couple of iterations it will not optimize it. Loops can be now optimized in-flight thanks to on-stack replacement feature which should help with startup time and also allow to apply Tier-1 compilation with more optimizations should the loop become hot (e.g. can't elide static initialization checks if you go straight to full optimized without Tier 0 -> Tier 1). To get more representative data it is best to either use BenchmarkDotNet or profile code close to real life case.
Please do not use this. JIT is designed with tiered compilation in mind for a long time. I cannot stress this enough, the number in the above comment is not representative. Using this setting is highly discouraged.
Please use BenchmarkDotNet to get accurate numbers!
There is no doubt but if you would like to accurately compare a part of your code on 6 vs 7 then the best practice is to use BDN with [SimleJob(RuntimeMoniker.Net60)] and [SimleJob(RuntimeMoniker.Net70)]. Make sure to set project to multi-target both versions. That way you will see actual difference, feel free to also add [MemoryDiagnoser] and [DisassemblyDiagnoser(exportCombinedDisassemblyReport: true)].
87 comments
[ 1.9 ms ] story [ 285 ms ] threadCongrats to everyone who fought vigorously to make it happen, screw the managers, execs and their surrounding noise, long live to the real engineers at Microsoft
Explains why my container got stuck packaging Kestrel this morning.
Presumably this would have implications for those using LGPL-licensed .NET libraries, especially those who'd like to distributed closed-source applications AOT-compiled using this approach?
Are there any commonly-used .NET libraries these days that are only LGPL-licensed?
I haven't done .NET development in a decade, so I don't really know the current state of affairs.
Side note: how does that fit in with cryptographic signatures? GPL v3 was written to combat "Tivoization" (open source, but can't replace the binary). Does the LGPL v3 disallow such things with DLL/so files (use hashes to prevent replacing the FOSS lib)?
NGEN, Singularity and Midori research (whose tech landed on Windows 8 MDIL and UWP .NET Native respectively), Mono AOT.
I always were the opinion that given Anders Hejlsberg background, .NET 1.0 should have had a better AOT story than NGEN.
We're about to start a project with those limitations and there really is no good choice now that .NET 6 is already a year through it's lifecycle.
[a]: Pass the `--sc true` option to `dotnet publish`: https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-p...
https://learn.microsoft.com/en-us/dotnet/core/deploying/runt...
You have a point, but I'd call out that migrating to newer releases can and often is trouble-free.
A couple of months ago I worked on a .NET Core 2 web service that was put on cold storage for a few years, and all it took to migrate it to .NET Core 6 was a few version number bumps and a rebuilding the project.
YMMV of course, but LTS shelf life might not be a deal breaker.
I say particularly, because Core2->Core3.1 was a fairly painful change for some.
I'd say the 66% worst case is 'you also have to add some compat flags and stories to properly resolve the compat flags'.
Until the date hits them in the face there’s no urgency.
It's not really Microsoft's job to work around your awkward requirements. Everything is open source, you can ship patches for .NET 6 yourself if you really want to.
Microsoft's general-ish LTS for .NET is 2 years. We also only seem to get a new release every 2 years. It's hard to handle breaking changes between two versions quickly.
What kind of breaking changes have been hard to handle?
https://github.com/nodejs/release#release-schedule
Biggest problem for us is .NET Standard. I don't even understand how it could work on a theoretical level. Maybe it could work if there was no dependencies.
Edit: The bindings that is. Maybe the devs too.
edit: Ok I see, it seems in that scenario loading the correct assembly is more difficult on dotnet framework and usually requires binding redirects to be specified. On dotnet core/.NET 5+ there are no issues though, which is why I haven't experienced this problem myself.
https://nickcraver.com/blog/2020/02/11/binding-redirects/#th...
We pretty much banned .NET Standard for any in-house dev.
This is why it's much better to move away from the shrink-wrap model of delivering software and focus on SaaS only solutions.
Many years ago I wrote software for a medical device. Before we could sell the device we needed to get it tested by Underwriters Laboratories to ensure it was safe (wouldn't shock people) and could be cleaned by hospital staff without damage. We also had to do the process to get the CE mark for it so it could be sold in the EU. And of course the FDA needed to approve it. It took nearly a year for all this, before we could offer it for sale and start marketing it.
So there's a third of the LTS lifetime consumed, right there.
We are also preparing for a move from .NET Framework 4.7.2 to .NET 6/7. It's going to be quite the project.
I don't foresee any issues going from 6 -> 7. 5 -> 6 was essentially just a find and replace on TargetFramework and it all just worked.
Seems like the only reasons for upgrading from 6 to 7 would be an easier path (possibly) to upgrade later than going from 6 to 8, or if you really want to use something in c# 11 (https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...) . I remain unconvinced...
In our case improved hit reload is very welcome. So I guess we will incremenet our runtime.
5 1107ms
6 1075ms
7 1211ms
Just number crunching and calling HashSet.
If you would like to have representative benchmark data, I suggest relying on BenchmarkDotNet instead.
Please use BenchmarkDotNet to get accurate numbers!