.NET 7 introduces Native AOT
devblogs.microsoft.com
devblogs.microsoft.com
Basically "ldd $file" needs to say "not a dynamic executable". Also, no dlopen().
- libcstdc++.so.6
- libm.so.6
- libgcc_s.so.1
- libc.so.6
You can also exchange some dependencies by compiling with profile linux-musl-x64 instead of linuxe-x64 (no libc, no libm, but with libc.musl-x86_64.so.1) to shrink everything down to the bare minimum.
While this isn't a completely statically linked executable, I think it's all you need for most distributions. The important part is that you don't need to install any runtimes on the remote machine to run the executable.
I'd love for dotnet to also get static compilation options to get rid of the last few dependencies but when your goal is to just distribute the binary so others can run it, I think dotnet is already there.
so, uh, what's wrong with g++ -static foo.cpp ? Note that however you cannot make something that will make any use of OpenGL if you do this as you would have to link statically against the GL implementation, thus forcing a specific driver and requiring a specific graphics card. It's also not possible at all on windows and macOS (unless you restrict to a specific point release there).
glibc is LGPL, so license incompatibility might ensue if you aren't using musl.
And it's far more than just OpenGL as an issue, there's PAM too among other things.
Windows and macOS don't have stable syscall ABIs in the first place.
So unless the vendor has a specific toolchain for stripping info from those (like NVIDIA for their kernel modules...) not a good option :/
The stopper I found was the abysmal debugging support, I hope that has improved in the meantime.
you want consistent perf, AOT makes more sense over there
Unity game devs for example had to fight with the mono JIT by warming up their gameplay code otherwise it'd introduce micro stutters
do a google search
a audio VST, a game, a CLI are not servers where JIT makes more sense (sometimes)
Minecraft was rewritten in C++ to increase performance on lower end devices and overall general performance (no longer need to warmup JVM to remove the stutters during gameplay, lower downtime for restarts in realm based servers)
https://old.reddit.com/r/Minecraft/comments/i27zzo/5_ways_th...
We can talk all day about high/low level languages, JIT/GC introduce overhead, that's it
When you only have 8ms for your framebudget at 120hz, every bit make the difference
The rest is handled on the GPU anyways, AOT compiled ;)
No that is cheating, IL2CPP is a C# to C++ transpiler.. Which is similar to writing a C++ program, interesting technology though. However it's true Unity also has a Burst compiler which is AOT is release mode and output LLVM IR. Look that is interesting and that is exactly where I wanted the conversation to go. GraalVM is generally slower on AOT than on JIT. I expect the same from .NET 7 AOT (haven't checked but is likely true) Unity Burst is interesting because it leverage an infrastructure that has received an enormous number of human resources and optimizations for AOT (LLVM). However Unity does not allow to benchmark Burst vs modern .NET JIT so it's very possible that Burst is in many cases slower than .NET JIT. This can't be verified easily and I'm not aware if Burst can be used outside of Unity but I guess one could write the same microbenchmark for both, it's just that no-one did it. However, Unity has gained a lot of technical debt because its own tooling (and Mono) are stuck on .NET 4.x They are apparently actively seeking to update their support and will leverage CoreCLR to some extent so maybe once it will be done, comparisons will become easier and they might or not replace Burst by regular CoreCLR, time will tell. https://forum.unity.com/threads/gdc-2022-the-future-of-net-a... https://forum.unity.com/threads/net-6-support.1059992/
> Minecraft was rewritten in C++ C++ is faster because it is lower level, my point is Minecraft do not use Java AOT. and as said many of minecraft stutters are avoidable GC pauses.
It's true 8ms is a tight budget indeed hence why ZGC is a key advance, a place where C# is currently inferior to java.
> The rest is handled on the GPU anyways, AOT compiled Haha nice try, I appreciate the tentative but I'm not sure you're being right. regarding the topic of compiling shaders for a 2D GUI, using a JIT is a key advantage, see e.g. https://github.com/blend2d/blend2d As for GPU drivers (handling openGL/etc) I think its a mix of both but I have forgotten the things I had read about them on phoronix Most game emulators strongly benefit from JITs shaders too.
Are we using two weights here?
C++/CLI is slower than normal C++.
Of course, sometimes JIT is faster. I remember gcj compiled code was plenty of times slower than code running under JVM.
I think there is no easy way to conclude which is faster, AOT or JIT.
Garbage collection also takes its toll. Looking at most benchmarks Go which is AOT compiled does not fare better than JIT-ed C# or Java.
For .NET I suspect there won't be much difference speedwise between AOT and JIT.
But AOT vs JIT has some other aspects. Like with Blazor who, at first, ran under a .NET virtual machine which ran under WebAssembly Virtual Machine. With AOT, things are simpler.
1) IIRC CLI is managed AKA garbage collected (BTW managed C++ is common practice e.g. chromium) 2) human resources, c++/cli has received much less optimization effort than LLVM/GCC/C#
as for Java https://github.com/oracle/graal/issues/1069#issuecomment-473... Go is the proof that GC-ed languages can be fast via AOT so it is not the discriminating factor. I suspect C++ with a GC is not much faster than JITed C# and the rest would be explained by other language brittleness such as e.g. the vtable hell, monomorphisation, etc Also weirdly, LLVM and GCC have received much more optimization human resources than openjdk and coreclr
> But AOT vs JIT has some other aspects. Like with Blazor who, at first, ran under a .NET virtual machine which ran under WebAssembly Virtual Machine. With AOT, things are simpler. well yes for this special case
CLI compiles to MSIL and runs on the CLR, so yes, very managed by default.
> c++/cli has received much less optimization effort than LLVM/GCC/C#
C++/CLI also found no regular users and people have been warned not to use it from even just months after its original release. From certain perspectives: It has really only had the one release in 17 years and been a "legacy tool" for most of that time.
(Possibly two releases if you count C++/CX, though that doesn't run on the CLR and is its own weird one-off thing for COM weirdness.)
> AOT may be bad for real time audio due to compile-time assumptions and other heuristics that are limited by the lack of run-time history.
> JIT is probably bad for real time audio, unless you take special precautions to pre-condition the execution context with a workload that approximate the live one.
How does this sound?
You could presumably JIT to a page, warm it up by running in a separate thread, then swap it in...
But for me, I'm not sure what gain that gives over AOT, and certainly adds background churn
Debugging is one area where the form factor will likely demand different behavior vs. JIT, so it will be an evolving scenario. It would be great to know what you would expect vs. what you saw, and importantly what you expect to be different from a traditional native debugging experience (like in C++).
I recognize it traditionally produced MSIL and this is a big breakthrough, just feel like the feature is kind of the whole point of a compiler.
Span<T> and its friends don't cover every scenario you might wish for "serious" systems programming, yet, but I wouldn't be surprised if the slow weird convergence with Rust borrow mechanics eventually makes C# look like a good option for systems programming, too.
https://docs.microsoft.com/en-us/dotnet/framework/migration-...
It already happened, that is what JIT caches with PGO feedback are all about, available out of the box in Android (yeah I know it isn't really Java), OpenJDK since version 9, OpenJ9 since ages, and on commercial JDKs like PTC, Jamaica, J/Rockit, since begining of the century.
.NET introduced PGO feedback around .NET Framework 4.6, but until now it has been quite hard to make use of, and there are some improvements coming up on .NET 7 to make it more automatic without the need to explicitly call some runtime APIs.
.NET has tiered compilation. https://docs.microsoft.com/en-us/dotnet/core/runtime-config/...
>JIT caches .NET has a native image cache. https://docs.microsoft.com/en-us/dotnet/standard/managed-exe...
>automatic vectorization
NET has automatic vectorization. https://docs.microsoft.com/en-us/cpp/parallel/auto-paralleli...
>devirtualization .NET suports both inlining and devirtualization. https://devblogs.microsoft.com/dotnet/performance-improvemen...
So, basically, none of the downsides you think about exist.
Maybe I do know one thing or two about what .NET is lacking versus Java in JIT/AOT department.
And whatever gains you get from that have to offset the fact that these languages incite patterns that are generally awful for cache coherency, and generate a lot of garbage.
Some C# microbenchmarks MAYBE could become faster than C++ in the future, but actual programs I think is extremely unlikely.
Wtf why?? Have you even the slightest idea if the breadth and the depth of a program's possible execution paths? It's a combinatorial explosion as show the difficulty and time of partial fuzzing.
Don’t hold your breath. The Java community has been trying to do that forever and no cigar. C/C++ is still the #1 language for high-performance software. Developers who hasn’t worked on high-performance software always underestimate how hard it is to compete with C/C++ when it comes to raw performance. Which is why new high-performance projects are started every day using C/C++.
What really bothered me were the IBM RAD Studio for Websphere 5.x start times back in 2005.
Now the few ms that PowerShell takes?
I can live with that, no need to go for breakfast while devenv is booting up.
C:\dev> (Measure-Command { pwsh -c exit }).TotalMilliseconds
1394.1826
C:\dev> (Measure-Command { pwsh -noprofile -c exit }).TotalMilliseconds
247.4816
Non-cold start on a 14-core Skylake-X. Drives me nuts.(Measure-Command { powershell(Measure-Command { powershell -c exit }).TotalMilliseconds 768.5885
(Measure-Command { powershell -noprofile -c exit }).TotalMilliseconds 113.3157
PS C:\Users\me> (Measure-Command { pwsh -c exit }).TotalMilliseconds
265.3785
PS C:\Users\me> (Measure-Command { powershell -noprofile -c exit }).TotalMilliseconds
119.481It's mind boggling that they are just now waking up, not having it makes it impossible to choose and recommend dotnet when your requisite is to be able to have something "tiny", fast and ready to go (no cold start, no runtime dependencies)
We talk a lot about Go, but Java had it for years with GraalVM, it should have gave them a hint
Of course there was alternative solutions for native AOT, but nothing as easy and integrated as: dotnet publish
It's nothing unusual. Software engineering as a field moves at a glacial pace. I see two reasons for this: one is that people don't want to learn anything radically different from what they know already, so you need generational change for new ideas to have a chance to come to fruition. It's a 10-20 years cycle. Then the other reason is that we basically don't know what we're doing, and so some of the new ideas are terrible in practice, reinforcing the first reason. How long did it take for mainstream languages to start seeing `null` as a problem and getting Option types? Depending on who you ask, it'll be 20-30 years; Haskell and other MLs had it either from day 1 or after inventing monads and Maybe (I'm not sure here), and Haskell introduced monads in early '90s. So it's at least 20 years since then, and yet we still have NullPointerExceptions here and there...
What other industries have you worked in that move faster than software? My experience is that the rate of change is so high and fast in so many areas it's impossible to keep up. Meanwhile in other industries version control still hasn't even gotten as far as track changes in word!
Yes. The rate of change is very high. Real, actual improvements, however, are very rare. Most of the code written today in Python - my field of expertise - is written almost exactly the same way it was since 2.4, when I started using it. C10k problem[1] is known for 20+ years already, yet Python only recently got async/await - a proven, very old technique often used for addressing the problem. I learned Rust earlier this year, and they also introduced async/await very recently. pg wrote about the technique in his "On Lisp" sometime in the '90s, so it probably was well known way before that. Scheme and Smalltalk, having reified call stacks in their respective ways, supported concurrency with lightweight threads since '80s. Now you hear about Crystal introducing fibers and how great they are. Yes, they are - and were, for the past 40 years. Rediscovered, and reimplemented, again, because nobody cares about the history of the field, everyone just wants to build their own thing, and solving puzzles is more fun than studying and then standing on the giants' shoulders.
Yes, git is a nice VCS, but to be honest - Subversion wasn't that bad, either. NetBSD still uses CVS for versioning and developing its packages. Yes, being able to work without a central server is an improvement, but then again: everything is hosted on Github, a central server, anyway.
Some terminal emulators experiment with displaying inline images. The new ones, Kitty and its ilk. First, they try to improve the protocol designed for teletypes in the '60s (IIRC), then they give up and introduce non-standard extensions, which limits their reach and usefulness. But then again, Kitty is hardly the first attempt - IPython qtconsole is also ~15 years old, and a decade before that TCL tried the same thing (with some success I hear).
One possible solution to the expression problem, namely multiple dispatch / multimethods, is a selling point of some new languages, like Raku, Nim, Clojure, and of course Julia. Multimethods are known since the '70s, too, yet not even one mainstream language has them as a feature.
There's a lot to be said about the churn on the Web, and I don't want to go there, but from the outside perspective, the only real change that happened sometime in the last decade was Let's Encrypt becoming CA. IPv6 adoption is the same as always, and we still need NAT traversal techniques that we used in the '90s. Other than that, everything people do with JavaScript was already done and tested decades ago. I mean, virtual DOM? That's basically what X windows are, and every other GUI out there does it, with invalidating objects and redrawing only obscured/damaged parts of an object, with double buffering to avoid flickering. The shadow DOM and web components - though I've no idea how widely they are used - make the same promise that vendors made when shipping widgets as DLLs to Object Pascal, later renamed Delphi. The only real progress, other than adopting HTTPS everywhere, was ditching Flash, ActiveX and Java applets. It really tells a lot that the most impressive progress happened because of removing something instead of adding.
There's a lot more. I don't want to dismiss the great work of a great many fabulous programmers. The progress is happening at all thanks to them. The average developer, however, is average, and does not have knowledge and skills to write something actually game-changing. They try all the time, though, because it's fun, and then the hype and mob mentality takes over on social media.
You could say that machine learning was a great development, but then again - neural networks were described in the '70s. It just so happened that massively parallel GPUs were a good way to speed up otherwise very demanding computations. Computation, might I add, mostly done in Fortran (blas, lapack), to this day.
I don't want to dismiss the progress we're seeing. I just wish programmers would actually, seriously study the history of our field before going off to create yet another framework. Despite being short, the history of our field is littered with incredible amounts of prior art, and improving upon that should be the goal, I think, not "rethinking and reimplementing" everything from scratch every 10 years.
EDIT: I forgot to answer your question: I only worked with software for all my life, I can't say anything about any other field. Most of them, though, have centuries or millennia of history, and they seem to efficiently manage that legacy, turning it into productivity. Maybe there's less objective need for change there, or in some cases the change is impossible due to regulations? Fields that came into being due to the IT revolution seem to be similarly stuck in change-without-progress cycles. Some social activities are like this, too. It might be simply a feature all young fields have. I'm guessing a lot of early airplanes crashed, some of them because of problems that were solved already elsewhere, but without anyone else knowing. The number/rate of failed software projects is staggering, just as a lot of early flying ended with a crash. I'm not sure there's a meaningful correlation, and I'm way outside of my expertise when talking about planes, but I can't help seeing our field as immature and moving very slowly forward. The blessing in disguise is that this time around, failed project doesn't often mean someone died.
The demand is not so strong, and the Windows world is extremely used to having bits of dynamic runtime; the entirety of COM, for example.
It does illustrate the tug of war that .NET has always struggled with. The things Microsoft want it for within the Windows ecosystem vs the "normal language" running server-side applications on Linux that a lot of the customers want.
However it is done at installation time with dynamic linking only.
And Mono has had it since ages, used by Unity and Xamarin.
This is the porting of UWP .NET Native to mainline .NET.
go build
and you get 1 portable tiny executablengen, .net native, mono etc, you need more steps, and you get a folder with a bunch of files and folders
that's why these solutions didn't took off
dotnet publish -p:PublishSingleFile=trueAnd check the small print on your platform as to whether it's really single file not requiring any other dependencies alongside it.
This no longer happens since .net 5.
go build
and you get 1 portable tiny executable, provided it is 100% Go code, without any dependency on cgo or OS APIs not packaged into the Go runtime.These solutions did take off, how do you think Unity games for PS, Xbox, Wii, Switch, Windows 10 UWP, and Xamarin apps for iOS/Android get delivered?
Or does it need a huge amount of supporting .NET libraries included also installed on the target?
Seems to be the case that you just need to install the Microsoft.DotNet.ILCompiler package, and then `dotnet publish...` with the desired target.