I don't think PowerShell is able to use Native AOT compilation. The blog explicitly states that loading extra code at runtime is not possible, but AFAIK this is required for PowerShell commandlets.
Native AOT is a great concept, I was hoping to use it to build VSTs and other kinds of music plugins without having to deal with C++, since the binaries it produces can export symbols.
The stopper I found was the abysmal debugging support, I hope that has improved in the meantime.
Couldn't you test plug-ins with JIT? Seems like only some minor performance caveats would apply. Tiered compilation would kick in on hot paths after a while.
this is a myth, AOT is generally slower than JIT for high level languages.
Yes though prewarming is underused and important see e.g. https://github.com/facebook/nailgun
minecraft is not faster on GraalVM AOT nor will be every Unity Game out there.
C++ is faster but not because it is AOT, it's because it is a lower level language which is more brittle and less permissive/dynamic.
AOT on high level languages reduce throughput for most uses, even with PGO.
Unity games now ship with IL2CPP, to benefit from AOT compilation, the language and its constructs remains the same, gone are the stutters people were experiencing
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)
> Unity games now ship with IL2CPP, to benefit from AOT compilation
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.
As for which is faster, I have a counter argument to your claims that JIT code runs faster than AOT compiled code for the same language.
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.)
disagree, an audio application (e.g. a livestream) will have audio changing at runtime, therefore, the critical hot and cold codepaths change at runtime, which a JIT will handle optimally with dynamic optimizations and deoptimizations.
A statis PGO profile can and does help AOT by marking functions as cold and hot however a single profile is very weak/unsufficent against the general variety of runtime uses/inputs. Hence a JIT is much more usage resilient in its performance profile, aside from the initial (and pre-warmable) cold start.
your disagreement doesn't change the fact AOT programs can become pathological by their a priori and not a posteriori tagging of hot and cold functions but hey free country, not assimilating valid arguments and being in denial is a human right.
Also I realize you said "pausing the world", are you confusing JITs with GCs? Or enlighten me what in a JIT induce a stop the world pause besides a GC.
As for this, it is hortogonal indeed, AOT java/C# still has a GC and has indeed SOTA submillisecond GC pauses with e.g. ZGC.
The fact is you don’t want unpredictable latency when processing audio. JIT produces unpredictable latency. This is a fact. You are saying that doesn’t matter, because in the end it is faster, but it totally misses the point about latency.
I have to say I am really appreciating the amount of conversation that arose here. My reading of this thread so far leaves me with:
> 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.
If you are doing anything realtime, it's also going to depend on your hardware as much as your software. The real answer, is it depends and it's all tradeoffs. There's no "right" answer, but generally, you want things to be predictable (something that AOT gets you), but if your performance budget gives you the ability to stop the world and JIT (because hardware), then that's ok too.
Audio doesn't change in those applications in a way that would affect the profile. They're very math-heavy pipelines (if we're talking about vst-style effect stacking) where branching is avoided as much as realistically possible. What's in the studio stream itself is largely irrelevant.
You generally do not want use NativeAOT for plugins, since you can have just one .Net runtime inside process. If somebody will write another plugin you will have a problem or experience very strange things
Thanks for the feedback! If you have some details and want to post them on https://github.com/dotnet/runtime, we can include them in planning. As you might have guessed, this is a pretty huge long-term project and many things basically need to be rebuilt from scratch in order to be supported.
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++).
The size improvement is going to be really interesting to me. Currently I have to choose between shipping small Framework 4.8 apps, or the whole kitchen sink with .net 6 even for a trivial wpf+ef app. Trimming and readytorun did not produce significant improvements unfortunately.
I haven't done much desktop/UI work but don't the small Framework 4.8 apps rely on the proverbial kitchen sink being pre-installed on a user's machine? Because afaik this is also possible with newer .NET [Core] applications, and indeed is the default. You just also have the option to publish and distribute a larger bundle which includes the runtime + required libraries.
Correct. The difference is that 4.7/4.8 came preinstalled on win10 for years now. It can be uninstalled so you can't really rely on it, but... 99% of the time it works. If not, you tell the customer to install it.
The UI frameworks are hopelessly interlinked. I can't even get it to trim out WPF from an all-WinForms app. I don't have any hope that this will improve substantially for desktop apps; I'm sorta just happy they're still supporting our desktop UI frameworks at all.
I don't get why people are repeating that. WPF is not dead, it's fully supported and the project has a future roadmap. (https://github.com/dotnet/wpf/blob/main/roadmap.md) MAUI is not taking over, it's not even released yet. We only just got a release candidate 3 this month. Looking at local job postings, WPF had hundreds of hits, while MAUI has... 3 "xamarin or maui" mentions.
The way to go, i wonder why it took them so long to have such feature, everyone around me is using Go, part of the reason why is single native static binary
It'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 mind boggling that they are just now waking up
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...
> Software engineering as a field moves at a glacial pace.
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!
> My experience is that the rate of change is so high and fast in so many areas
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.
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.
This produces a self-unpacking executable that drops all the assemblies somewhere and then runs it. There can be surprising side effects. https://github.com/dotnet/runtime/issues/59715
And check the small print on your platform as to whether it's really single file not requiring any other dependencies alongside it.
Not really - it already compiles C#, F# and VB.NET to .NET bytecode, which can be JIT compiled by the runtime to some optimized native code as the program runs. It's just that the native code can now be produced by the .NET SDK during the initial build ("ahead of time").
I really appreciate the rate of optimizations going on in .NET, I feel like openjdk focus less on optimizing codegen and intrinsics (although it does it well compared to other languages).
I even speculate C# will reach a point where it will be faster than real world C++ code in many cases. One reason being that GCC/LLVM have mostly stalled performance wise, with only ~1% increment per years (except in very specific cases), and the JIT model should be superior IMHO, I don't understand why JITs can't have a long AOT passe just like LLVM and switch to runtime JIT opts/deopts only if it is superior. This will happen, the question is when?
.NET still has some catch up to do with JVM eco-system (there is more than OpenJDK out there) in tiered compilation, JIT caches, automatic vectorization (Intel contributed AVX support), devirtualization.
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.
I have been doing Java and .NET since they exist, .NET even before it was launched thanks to working for a Microsoft Partner that was part of the launch event in Portugal, which gave us access to early builds, the famous MSDN discs with documentation written in red.
Maybe I do know one thing or two about what .NET is lacking versus Java in JIT/AOT department.
As someone who is a career-long C# developer (back to the public beta) who wouldn't touch Java, I think we can be a little more fair here. We in the C# world only recently got tiered compilation and there still isn't an interpreter-based first tier like Java has. Your automatic vectorization link is about C++, not C#; I don't think C# has it. I think OP may be wrong about the devirt, as you state, but I wouldn't be surprised to find that Java can devirt in more situations than C# can due to working on it more. OP probably knows more about it than I do.
It's true .NET is lacking autovectorization support.. (despite leveraging a huge number of intrinsics) however the explict SIMD API of .NET is more complete than the Java Vector API, for advanced use cases.
The hypothesis that JIT can be faster than C/C++ because it can adapt code during runtime is mostly nullified by PGO. Yes, you could argue that in some programs the execution path might drastically vary and the profile obtained during compilation is not representative to the actual run. But that's probably very unlikely.
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.
> I even speculate C# will reach a point where it will be faster than real world C++ code in many cases
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++.
Java is only as fast as C/C++ if you completely avoid creating objects. It is the ability to manipulate raw data in a cache optimum way and without the Java/C#/… imposed overhead that makes C/C++ fast. Trading doesn’t touch much data so I am not surprised that Java is OK there.
If this can produce static executables on Linux we may have a winner. We are in the process of selecting a language for $product and we need to pick one everyone is happy with, that boils down to static ELFs. My pick would have been Nim or perhaps ChowJS if it works like they say it does, but it would be even nicer if C# was a possibility.
Basically "ldd $file" needs to say "not a dynamic executable". Also, no dlopen().
Currently, dotnet is able to build binaries for Linux that only depend on the following libraries (hello world app, according to readelf -d):
- 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.
It's remarkably hard to ditch dynamic loading completely when using GNU libc, even when writing directly in C. A surprising range of POSIX functions require it - anything touching usernames, for example, requires it in case it's running on a complex PAM setup.
please provide substance, this mere dismissal seems ungrounded, GraalVM native in most cases just works(tm). There is some config if you make heavy use of reflection and that is pretty much all.
It in most cases just does not work. I have never been able to compile a non-trivial project with graal unless I’m using some framework like Quarkus. As soon as there’s any of type of dependencies involved you are going to hit hidden complexities around reflection and class loading.
Kotlin native or graalvm AOT?
The new kotlin K2 frontend should help a lot but it won't be stable until 1 year.
Also JIT for development and AOT for releases seems very viable to me
Well, I'm looking forward to updating my tests of .NET 6 (with the previous AOT functionality, things were already pretty promising, even for GUI apps): https://taoofmac.com/space/blog/2021/11/14/1600
> Basically "ldd $file" needs to say "not a dynamic executable". Also, no dlopen().
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).
Now, if they would also introduce a way to disable GC and do manual memory management, C# could tackle more systems programming, too, becoming the supreme Jack of All Trades. It's used for: backend, desktops, frontend (with Blazor), desktop, mobile and even microcontrollers.
Span<T> and friends is having manual memory management cake and eating it in a GC managed world too. So far as I'm aware they weren't directly "designed for" systems programming, but there's a growing impressive body of work that a lot of the benefits to raw memory management and "pointer arithmetic" you can get from type safe stack-only "borrowable" functors in a GC language/environment.
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.
112 comments
[ 3.1 ms ] story [ 171 ms ] threadWhat 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.
(Measure-Command { powershell(Measure-Command { powershell -c exit }).TotalMilliseconds 768.5885
(Measure-Command { powershell -noprofile -c exit }).TotalMilliseconds 113.3157
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++).
https://docs.microsoft.com/en-us/dotnet/framework/migration-...
It'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...
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.
ngen, .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
And 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.
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.
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++.
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 :/
https://www.wildernesslabs.co/
https://docs.microsoft.com/en-us/dotnet/api/system.gc.trysta...
https://docs.microsoft.com/en-us/dotnet/api/system.runtime.i...
https://docs.microsoft.com/en-us/dotnet/api/system.runtime.i...
Go have fun!
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.
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.