Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Early adopters can experiment with native AOT form factor #248

Closed
3 of 5 tasks
Tracked by #5366
samsp-msft opened this issue Oct 19, 2020 · 78 comments
Closed
3 of 5 tasks
Tracked by #5366

Early adopters can experiment with native AOT form factor #248

samsp-msft opened this issue Oct 19, 2020 · 78 comments
Assignees
Labels
area-NativeAOT-coreclr .NET runtime optimized for ahead of time compilation Epic Groups multiple user stories. Can be grouped under a theme. Priority:0 Work that we can't release without Team:Runtime

Comments

@samsp-msft
Copy link
Member

samsp-msft commented Oct 19, 2020

This is a draft/proposed User Story and not committed for .NET 6.0 yet.

We have seen a surge of interest in statically linked binaries with minimal dependencies in recent years. This is a reversal of a multi-decade trend to deliver dependencies as shared libraries. The benefits to deployment and the ability to optimize a single app outweigh the benefits of sharing for certain types of workloads. The gain is most significant for workloads with a high number of deployed instances: cloud infrastructure, hyper-scale services, popular apps or games. The number of apps of this type is relatively small, but they are highly visible, impactful, and often cost a lot of money to operate (savings can be meaningful).

Emerging programming environments (e.g. Go, Rust) tend to be designed for this form factor. Established programming environments are catching up on this trend to be relevant for this highly visible segment, for example Java Graal, Dart, Kotlin/Native.

Various implementations of .NET (Xamarin, Unity, .NET Native) have demonstrated that .NET is well suited to native AOT in terms of fundamentals, however, there are tools experience and ecosystem challenges that currently prevent .NET from being a great general purpose solution. We intend to start addressing these issues with this project. It is very likely that the first set of improvements will have rough edges that may prevent adoption for some developers. We will use feedback to determine which experience issues to prioritize. We are also not comitting to any particular end point for this project, at this time.

This high level section sets our intention to invest in native AOT scenarios and more definition from the teams will be needed to define our phased approach over the next few .NET releases.

Work Items / User stories

  • TBD
@samsp-msft samsp-msft changed the title User Story: .NET 6 will take the first steps to enable Native AOT User Story: Start the journey to enable Native AOT in runtimelabs Oct 19, 2020
@samsp-msft samsp-msft transferred this issue from dotnet/runtime Oct 19, 2020
@masonwheeler
Copy link

Be careful to define this properly. A "JIT-less native AOT" is not a good idea. Far too much of the .NET ecosystem depends on the JIT being there for one reason or another. A far better goal is to AOT everything that can be determined statically, and then leave the JIT in there for when it's needed. It doesn't have to be an either/or thing. Just another example of Anders Hejlsberg's principle: static where possible, dynamic when necessary.

@PJB3005
Copy link

PJB3005 commented Oct 19, 2020

@masonwheeler certain platforms like e.g. iOS don't allow JITs, I believe. Supporting a JITless scenario is the only option there.

I believe the "AOT and JIT at once" scenario is already filled by ReadyToRun, no?

@masonwheeler
Copy link

masonwheeler commented Oct 19, 2020

@masonwheeler certain platforms like e.g. iOS don't allow JITs, I believe.

Then we shouldn't support them. Particularly iOS; why legitimize a system that's spent over a decade being actively hostile to you? Like a person in an abusive relationship, attempting to appease them never makes anything better; the only correct choice of action is to walk away.

I believe the "AOT and JIT at once" scenario is already filled by ReadyToRun, no?

Not really. It doesn't go anywhere near far enough in AOTing things that can be AOT'd; as soon as a problem starts to look even a little bit difficult it punts it off to the JIT. I say, aggressively AOT everything that can be AOT'd, and leave the JIT only for things that legitimately require it.

@RalfKornmannEnvision
Copy link

@masonwheeler certain platforms like e.g. iOS don't allow JITs, I believe.

Then we shouldn't support them.

This would cut the option to support game consoles, too. As far as I remember there were quite some interest for native AOT from game developers in the survey. 

@PJB3005
Copy link

PJB3005 commented Oct 19, 2020

This would cut the option to support game consoles,

Indeed, I believe that none of the game console platforms allow JITs either (though of course detailed info on this kinda stuff will be behind NDAs).

There's a reason Mono AOT is necessary, and also Unity's IL2CPP.

Then we shouldn't support them. Particularly iOS; why legitimize a system that's spent over a decade being actively hostile to you? Like a person in an abusive relationship, attempting to appease them never makes anything better; the only correct choice of action is to walk away.

Not getting into any of the "abusive relationship" stuff... not supporting iOS is a huge market missed and also means Android is less viable (no ability to share code). That's not practical.

Not really. It doesn't go anywhere near far enough in AOTing things that can be AOT'd; as soon as a problem starts to look even a little bit difficult it punts it off to the JIT. I say, aggressively JIT everything that can be JITted, and leave the AOT only for things that legitimately require it.

Did you mix up "AOT" and "JIT" in your last sentence? At first you say it AOTs too little but then you say it should JIT as much as possible.

@masonwheeler
Copy link

@RalfKornmannEnvision Which game console forbids JITs on their platform? I've only ever heard of Apple doing that with iOS. (It's quite possible that I haven't heard about it on consoles because of NDAs or whatever, but the fact remains that I haven't heard about it happening anywhere other than iOS. Do they have a problem with JITs in general, or just with runtime generation of executable code in-memory, and if the latter, could the IL interpreter be employed?)

@masonwheeler
Copy link

masonwheeler commented Oct 19, 2020

@PJB3005

Did you mix up "AOT" and "JIT" in your last sentence? At first you say it AOTs too little but then you say it should JIT as much as possible.

Oops, you're right. Fixed now.

Not getting into any of the "abusive relationship" stuff... not supporting iOS is a huge market missed and also means Android is less viable (no ability to share code). That's not practical.

That's what we call "penny wise and pound foolish." The "abusive relationship stuff" is my entire point: iOS is a system that is actively hostile to both developers and users, and we ought to treat it as a pariah and actively work to delegitimize it and disempower it, rather than appeasing their ever-worsening demands in the hopes of catching a few crumbs from their table.

@RalfKornmannEnvision
Copy link

@RalfKornmannEnvision Which game console forbids JITs on their platform? I've only ever heard of Apple doing that with iOS. (It's quite possible that I haven't heard about it on consoles because of NDAs or whatever, but the fact remains that I haven't heard about it happening anywhere other than iOS. Do they have a problem with JITs in general, or just with runtime generation of executable code in-memory, and if the latter, could the IL interpreter be employed?)

Every modern game console doesn't allow to generate any kind of executable code at runtime. It's part of the security system. 

You can always run an interpreter but on a system like the Nintendo Switch I would honestly prefer to have an option to not depend on it even if it means that I lost some features.Developers who already use one of the C# solutions for these platforms are already aware of such limitations. But using RyuJit instead of Mo0no AOT would mean an significant performances improvement. 

@masonwheeler
Copy link

masonwheeler commented Oct 19, 2020

I don't understand why people want to force the JIT into people's program

To cover the edge cases. If you have code that's using dynamic code generation (expression trees, serializers, etc,) calling reflection features such as MakeGenericType, or using recursive generics, these are things that simply cannot be evaluated at compile-time because they depend on information that isn't available until runtime.

If the AOT can prove that the program doesn't use any of this, it's free to leave the JIT out. And if the execution never uses these features, it will never need to fire up the JIT. But saying "here's this feature that massive amounts of the existing .NET ecosystem touch in one way or another, and we're going to place all of that existing code off-limits if you want good AOT" just leaves a bad taste in my mouth.

@PJB3005
Copy link

PJB3005 commented Oct 19, 2020

These kinds of edge cases are better solved in ways such as better compile time code generation, which we are getting with C# source generators for example.

@masonwheeler
Copy link

for edge cases, edge solutions, it should be opt-in, not opt-out, default should cover what people expect when they AOT compile

What people expect when they use .NET code is .NET code that works. That should always be the highest priority.

@PJB3005
Copy link

PJB3005 commented Oct 19, 2020

What people expect when they use .NET code is .NET code that works. That should always be the highest priority.

I fail to see how this is mutually exclusive?

@masonwheeler
Copy link

These kinds of edge cases are better solved in ways such as better compile time code generation, which we are getting with C# source generators for example.

Oh, I definitely agree. And if source generators were actually any good, that would be amazing. But they aren't. The current implementation of generators really sucks, and the Roslyn team is firmly committed to making sure they never stop being sucky, because good metaprogramming is incompatible with something they hold as a much higher value: ensuring that everything will execute very quickly and never make Intellisense have to wait. (Not exaggerating. This is the result of many exasperating conversations with team members who are completely unwilling to budge on this point. Visual Studio UX trumps language quality any day of the week.)

@RalfKornmannEnvision
Copy link

What people do with their code is their problem, they should be educated when they use LINQ and abuse generics, or emit code at runtime etc etc etc

I don't think that this would be a big problem. Developers are already using Xamarin on iOS, Unity or Mono AOT today All of these have limitations compared to the full .Net experiences  

But even if there are already working solutions for AOT I still like to see am offical supported solution that is based on the current .net development. Because based on own experiments I know that the RuyJit based CoreRT solution generates much better results than Mono AOT.

@masonwheeler
Copy link

Other languages doesn't have this issue, and we see more and more "high level" system languages, many of them proved that these solutions made at runtime can be done at compile time, and be much cleaner and more efficient

Rust does it by having actual metaprogramming, of the type the Roslyn folks refuse to consider. Not sure which other languages you're referring to. The only other "high level system language" that's gained any traction in recent years is Go, and Go is basically awful all around in this area.

@HurricanKai
Copy link
Member

Oh, I definitely agree. And if source generators were actually any good, that would be amazing. But they aren't. The current implementation of generators really sucks, and the Roslyn team is firmly committed to making sure they never stop being sucky, because good metaprogramming is incompatible with something they hold as a much higher value: ensuring that everything will execute very quickly and never make Intellisense have to wait. (Not exaggerating. This is the result of many exasperating conversations with team members who are completely unwilling to budge on this point. Visual Studio UX trumps language quality any day of the week.)

The current version of source generators isn't great, that's true. But it'll be improved. And imo it's very important we keep the fast nature of Roslyn. Do we really want another C++ with a build process more complicated then your code, and longer compilation time then Runtime? (exaggeration, of course, but you get the point)

Roslyn is very very powerful and it's not at its limits with source generators at all, theres lots of improvements to be made imo, but I don't doubt they'll be made for one second.

Also, I believe the only thing the Roslyn team refuses to consider is code removal/rewriting. Not sure what everyone thinks this will do for them, but to my knowledge another core principle of the Roslyn code base is immutability, and this makes sense from a language design perspective too, I've never heard a single compelling case for code rewriting. There are already security concerns with analyzers, and even more of them with source generators...

@masonwheeler
Copy link

Also, I believe the only thing the Roslyn team refuses to consider is code removal/rewriting.

And given that rewriting is the single most useful feature of metaprogramming, my complaint stands.

@pjmlp
Copy link

pjmlp commented Oct 19, 2020

Thanks for reconsidering the status of AOT support.

@zakbaig
Copy link

zakbaig commented Oct 20, 2020

Would be absolutely amazing if Blazor switches to using NativeAOT (assuming it uses CoreRT as its base). CoreRT produced much smaller binaries than Mono’s AOT effort while still producing best in class performance. It would solve the question of “can I use Blazor for a massive public facing website?” as AOT Wasm is extremely fast so there’d be no performance penalty of using Blazor over JavaScript SPA frameworks, and the start-up time would, in theory, only be slightly slower than these aforementioned frameworks.

I’m convinced that if Microsoft want Blazor to be the go-to answer for web development then it needs to use the gold mine that is CoreRT. There’s only a few too many uncomfortable trade-offs a person has to make when using today’s Blazor but they can be eliminated entirely with a good NativeAOT/CoreRT story. Begging MS to pursue this.

@MichalStrehovsky MichalStrehovsky added the area-NativeAOT-coreclr .NET runtime optimized for ahead of time compilation label Oct 20, 2020
@TimPosey2
Copy link

TimPosey2 commented Oct 20, 2020

I'd also add in that LLILC could pair nicely with a native AOT implementation to target multiple backends and optimizations via LLVM. Auto-vectorization comes to mind.

@RalfKornmannEnvision
Copy link

I'd also add in that LLILC could pair nicely with a native AOT implementation to target multiple backends and optimizations via LLVM. Auto-vectorization comes to mind.

The issue with LLILC is that you will lost all the special net optimization's that are done by RyuJit. Because of this there is the idea to to to use a combination of RyuJit and LLVM. First let RyuJit convert and optimize the MSIL code to the CPU independent internal RyuJit intermediate format. Than instead of generating code for the target CPU the RyuJit format can be converted to LLVM. This will allow future optimization's that are beyond the limitations of RyuJit. This way you can get the best of both worlds. But this is even further away than NativeAOT.

@charlesroddie
Copy link

COM interop needs to be added because it's the most impactful thing tracked in this repo, and it would fix a major regression in the ecosystem by replacing netnative. System.Text.Json and EventSource source generators and precompiling regex code are nice-to-have features rather than essentials, while COM interop opens up frameworks where native AOT can immediately get real usage, with large benefit for developers and users.

The title of this issue is not ambitious enough because early adopters can already experiment with native AOT form factor, and they have been able to experiment with it and even use it in production for years! It was better before: "Developers can compile .NET apps into native executables (native AOT form factor)".

@wjk
Copy link

wjk commented Jan 3, 2021

My opinion on the matter: I, today, can take a .NET 5 Windows Forms project, run it though NativeAOT, and have the window appear as expected. (When you try to do anything further you get a crash due to missing COM support.) However, these days I use WPF. WPF uses C++/CLI in two of its assemblies: DirectWriteForwarder and ReachFramework. I have never used ReachFramework (hell, I don't even know what it does), but DirectWriteForwarder is an integral WPF component, very near the root of the dependency graph.

You can create a lot of crazy MSIL code using C++/CLI. I fully understand that it is impossible to support every possible C++/CLI assembly out there. However, not supporting any C++/CLI immediately rules out usage of WPF with NativeAOT. This would be a dealbreaker for me, as I (and many others) write 100% WPF applications because WPF is the only actually usable C# GUI toolkit available. (Windows Forms looks extremely dated, and WinUI 3 is nowhere near usable yet.)

@hez2010
Copy link

hez2010 commented Feb 28, 2021

WPF is the only actually usable C# GUI toolkit available. (Windows Forms looks extremely dated, and WinUI 3 is nowhere near usable yet.)

@wjk You may try out Avalonia, which is a WPF inspired, native-aot compatible and cross-platform UI framework, providing almost the same experience with WPF.

@wjk
Copy link

wjk commented Feb 28, 2021

@hez2010 I actually have already extensively experimented with that technology, but thanks for the pointer!

@cyraid
Copy link

cyraid commented Apr 4, 2021

WPF is the only actually usable C# GUI toolkit available. (Windows Forms looks extremely dated, and WinUI 3 is nowhere near usable yet.)

@wjk You may try out Avalonia, which is a WPF inspired, native-aot compatible and cross-platform UI framework, providing almost the same experience with WPF.

Seems like it's only setup for Mac OSX Native right now? (looking at the source)

@mrhelmut
Copy link

From our perspective on the FNA project, the JIT would actually be quite problematic if it were even an option, as it adds a pretty significant amount of ambiguity for portability (which is what AOT's use case is for game development in the first place). Typically you want either all-JIT or all-AOT, anything in the middle is just giving you the same amount of work that you get from transitioning between the two, but now you're stuck having to untangle things if someone does end up wiring the JIT into an AOT environment where JITs are explicitly not allowed (read: every single console and mobile environment).

Serialization and dynamic loading are not a zero-step process to port, but under absolutely no circumstances have we found this to be insurmountable, nor have we found that the solution that was ultimately developed was not worth the development costs, even without factoring that the whole reason that AOT for .NET exists is because JITs are explicitly banned in most environments. jkotas can't name names, but I can, so a couple real-world examples from me:

  • For FNA games like Dust: An Elysian Tail and Solaroids, the most common trip-up is the ContentManager - XNA Content depends pretty heavily on .NET serialization and reflection, so the expectation is that you'll load the type info dynamically from the managed assemblies and it'll all "just work". This is not true in console environments, but BRUTE has a config file for exactly this issue - you explicitly list the content types that would otherwise get missed by the type spider and it works perfectly fine after that. Ignoring that JITs are banned to begin with, a single config file is a lot easier to maintain than a JIT plugin in this case. At most it's about a day of work if you got a little too carried away with templates.
  • For reflection-heavy FNA games like River City Ransom: Underground and Streets of Rage 4, all the game logic risks being extremely dependent on what a JIT can do, and an AOT would fall flat on its face. Rather than wedge in a JIT, however, both studios independently made their own IL emitter that writes all that information at authoring time, making it more usable in environments like CoreRT. It took some work, but it also turns out that it works well in a JIT environment too since you can get a lot of busy work done at startup instead of letting jitters happen in the middle of gameplay (a similar issue is graphics pipeline caches and shaders; you may have seen modern games do a "first-start" load to compile all shaders to avoid stuttering during gameplay).

If you want both, target both separately. The likelihood of the two targets being any different even after jumping through AOT hoops is, in our experience, always zero by the end. To put it plainly: We would not trust developers to use a JIT plugin responsibly.

I would like to back Ethan's comment as a MonoGame contributor and in regard to my position at Flying Oak Games (we make, and port games to consoles).

NativeAOT, as it is now, has been an extremely valuable project and several relevant projects have been shipped with it to wide audiences. This includes Streets of Rage 4, Carrion, ScourgeBringer, River City Ransom: Underground, Dust... which all shipped to Windows, macOS, and Linux, and to more than 100k players each.
The tech is clearly appreciated for its efficient and bloat-free approach of AOT compilation. We can clearly say that it has been battle-tested for games. Even third-party providers like Epic or GOG have shown us good support and were keen to update their own C# API to be specifically NativeAOT-friendly.

I would also very much back the counterproductivity of AOT+JIT in that context. C# game developers are very used to work without a JIT (they want to avoid it at all cost because it is visible during gameplay, and a forced AOT is an excellent benchmark to proof a code to work without JIT) and without reflection because most console runtimes don't support it in favor of aggressive AOT. As mentioned by Ethan, game developers are more into pre-generating serializers (e.g. with protobuf) than relying on runtime IL emition (this is a trend that I can clearly confirm).

In regard to reflection, BRUTE (the AOT compiler used for FNA and MonoGame on consoles) is using a very straightforward xml description file to let the compiler know which types should be included if they were to be trimmed by spidering. It works great as it is.

TL;DR; NativeAOT is a very relevant, appreciated and battle-tested project as it is for game development, and I would very much support its integration as an official .NET form-factor.

@ryancheung
Copy link

I'm also making a mmorpg game that have both client and server written with dotnet 6 and built with NativeAOT. NativeAOT provides more efficient code, and most importantly for me, it protects my source code almost as c++ would do.

@agocke
Copy link
Member

agocke commented Aug 16, 2021

We've hit our targets here for 6.0 -- new architecture support (ARM64 on Linux and Windows) and many bugs fixed. Huge amounts of netcoreapp libraries have been annotated for trimming (dotnet/runtime#43543) which is the most important indicator of NativeAOT compatibility. Many libraries have even been made safe for trimming, like the source generators for System.Text.Json (dotnet/runtime#1568). We've also started adding more CoreCLR feature support to NativeAOT, like default interface implementations and covariant returns.

This is just the start of NativeAOT work, but .NET 6 has tons of improvements. We'll soon start planning for .NET 7 and we'll see what else we can do for NativeAOT and how the improvements can fit into the broader .NET 7 release.

@agocke agocke closed this as completed Aug 16, 2021
@zezba9000
Copy link

zezba9000 commented Nov 10, 2021

Have any experiments been done that just compile (C# => LLVM => ASM) OR (C# => ASM) directly?
In that you skip IL completely. One benefit langs designed around AOT runtimes is more of the runtime & implementation details can be updated faster which means performance issues caused from legacy IL baggage don't become blockers for basic features. Or one lang isn't limited because of the limitations of other langs.

Another thought: If a new C++ feature comes out, older compilers can't parse the headers & thats fine. Same concept should apply to .NET binaries. Seems like its far to often newer C# features take forever to be considered because of older runtime compatibility nonsense. This really needs to be mitigated more and newer runtimes designed to handle newer lang features in performant manors should be the focus. Thats a hard Pro over any minor Cons IMO. This would allow features like fixed multi-dimensional arrays & fixed non-primitive arrays to be added very quickly I would imagine.

AOT has valuable lessons that seem to be getting missed in the .NET / JIT world IMO.

@sgf
Copy link

sgf commented Nov 10, 2021

.net 6 has been release,but seems both (AOT or Native) not included.

@mxashlynn
Copy link

If anyone has the time, a brief summary of the state of AOT in .Net 6 including how early adopters can begin experimenting with it would be greatly appreciated. 🙂

@jkotas
Copy link
Member

jkotas commented Nov 10, 2021

Have any experiments been done that just compile (C# => LLVM => ASM) OR (C# => ASM) directly?

While these experiments can be interesting research projects, they would lead towards a complete reset and fork of .NET ecosystem. We do not believe that it would be a viable strategy. See ingredients of successful native AOT support in https://github.com/dotnet/designs/blob/main/accepted/2020/form-factors.md#native-aot-form-factors

C# features take forever to be considered because of older runtime compatibility nonsense.

It used to to be the case with .NET Framework. We are well pass that. We have been adding new core runtime features in every .NET Core release that are not present in older runtimes.

@jkotas
Copy link
Member

jkotas commented Nov 10, 2021

.net 6 has been release,but seems both (AOT or Native) not included.

.NET had different forms of AOT since forever. https://docs.microsoft.com/en-us/dotnet/core/deploying/ready-to-run is form of AOT for server and desktop included in .NET 6. There is also AOT for wasm and mobile form factors.

how early adopters can begin experimenting with it would be greatly appreciated.

NativeAOT packages are published on experimental feed. It is enough for early adopters that we have been in contact with to experiment with it. See https://github.com/dotnet/runtimelab/blob/feature/NativeAOT/docs/using-nativeaot/compiling.md for how to use it.

@zezba9000
Copy link

zezba9000 commented Nov 10, 2021

It used to to be the case with .NET Framework. We are well pass that. We have been adding new core runtime features in every .NET Core release that are not present in older runtimes.

-- This is only partially true. Which is why I specifically brought up "fixed multi-dimensional arrays & fixed non-primitive arrays" which are being blocked by MSIL & legacy runtime compatibility issues with said IL (which is what needs to be mitigated). And thats just the one I know of because I've wished this part of the lang was feature complete for years. I'm sure their are others in this category.

@jkotas
Copy link
Member

jkotas commented Nov 10, 2021

"fixed multi-dimensional arrays & fixed non-primitive arrays" which are being blocked by MSIL & legacy runtime compatibility issues with said IL

fixed arrays are a type system concern. IL is just one of the many places where the .NET type system is materialized. Other places include language compilers, AOT compilers, runtime, reflection APIs, debuggers, and all sort of other tools. Adding new core concept requires touching most of these. The problem is updating all these places, not in updating the IL alone.

@zezba9000
Copy link

zezba9000 commented Nov 10, 2021

fixed arrays are a type system concern... The problem is updating all these places, not in updating the IL alone.

  • I understand but this is true for any feature and the type / object system in the C# lang is already there for this as its recognized just not compilable to existing IL as it would seem by the kind of errors you get.

  • The "fixed-array" example illustrates how the IL / runtime methodology the .NET team is using artificially limits runtime / IL updates on sadly non-feature-complete areas for the sake of legacy runtime compatibility (which is a artificial limitation many AOT langs like C++ don't have in this specific area)... and my thinking is if the .NET team would worry less about C# compiler compatibility so it can target older .NETFW 4.x runtimes etc this wouldn't be an issue. A .NET DLL is more like a C++ header with a .lib/.dll where the JIT compiles & links .obj files. IMO .NET JIT should be considered in a similar light to C++ compilers in terms of what is allowed to be considered breaking changes in its meta-data (in C++ terms its header file).

  • Not to be redundant but IMO again you can't compile against modern C++ with old C++ compilers and the same should be true for .NET & its JIT (compiler)... if that makes sense.

@jkotas
Copy link
Member

jkotas commented Nov 10, 2021

my thinking is if the .NET team would worry less about C# compiler compatibility so it can target older .NETFW 4.x runtimes etc this wouldn't be an issue

I respectfully disagree. Maintaining C# compiler compatibility so it can target older .NETFW 4.x runtimes adds less than 0.1% overhead to everything we do today.

you can't compile against modern C++ with old C++ compilers and the same should be true for .NET & its JIT (compiler)

That's true for .NET today. You cannot run modern .NET 6 C# with old .NET Framework. The opposite works though: you can compile and run old C# code with latest .NET 6. Just like it is with C++.

@zezba9000
Copy link

zezba9000 commented Nov 10, 2021

Maintaining C# compiler compatibility so it can target older .NETFW 4.x runtimes adds less than 0.1% overhead to everything we do today.

But not always in the most optimal/performant way.
.NET assemblies behave like native ABIs in their virtual machine but IMO feels like this is going down the path of saying ASM never needs to change because the architecture it runs on will never change. I don't think thats inline with reality. I think long run thats a failed concept & while .NET has done great work it can start to show after awhile.

Anyway don't mean to drag this on forever...

@PJB3005
Copy link

PJB3005 commented Nov 10, 2021

Have any experiments been done that just compile (C# => LLVM => ASM) OR (C# => ASM) directly?

Unity's Burst is basically an alternative optimized compiler as far as I know, and I think it still just takes in IL. (IIRC) In a blog post they mentioned that re-using the (relatively) high level IL emitted by the C# compiler was much easier than making a completely alternative C# compiler (or language altogether). Of course it's still a specialized case, but it's something to consider.

This would allow features like fixed multi-dimensional arrays & fixed non-primitive arrays to be added very quickly I would imagine.

I don't know about non-primitive arrays ,but my understanding is that the runtime barely even knows what fixed is, at least from me looking at the IL output by the C# compiler. It sounds like multi-dim arrays would be totally possible since it's mostly C# side. (compiler just emits an internal type that is the right length for the fixed buffer and translates accesses to it, right? Can just have the compiler support multi-dim stuff)

@masonwheeler
Copy link

Multi-dimensional arrays already exist. According to the CLI spec:

I.8.9.1 Array types
An array type shall be defined by specifying the element type of the array, the rank (number of
dimensions) of the array, and the upper and lower bounds of each dimension of the array

This is supported in the C# language through multidimensional array syntax.

@PJB3005
Copy link

PJB3005 commented Nov 10, 2021

I believe @zezba9000 is referring to fixed arrays instead like:

struct Foo
{
	public fixed byte Bar[32];
}

@jkotas
Copy link
Member

jkotas commented Nov 10, 2021

It sounds like multi-dim arrays would be totally possible since it's mostly C# side.

Yes, for fixed arrays of primitive types only. If you would like to have fixed arrays of non-primitive types, allow fixed array to show up in signatures, or access them via reflection, there is some level of runtime support required.

See dotnet/runtime#61135 and related issues. This topic is best discussed there.

@zezba9000
Copy link

zezba9000 commented Nov 10, 2021

@PJB3005 I was referring to these incomplete lang features. (None of which compile atm)

[StructLayout(LayoutKind.Sequential)]
struct MyStruct
{
  // some fields
}

[StructLayout(LayoutKind.Sequential)]
unsafe struct Foo
{
 public fixed MyStruct Items[123];// single-dimensional fixed-array with custom-struct
 public fixed MyStruct Items[123][28];// multi-dimensional fixed-array with custom-struct
 public fixed float Items[123][28];// multi-dimensional fixed-array with primitives
}

@sgf
Copy link

sgf commented Nov 11, 2021

for (custom struct) fixed-sized-buffers
dotnet/csharplang#1314
https://github.com/dotnet/csharplang/blob/main/proposals/fixed-sized-buffers.md

.net 6 -C#10 ,no processing yet .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-NativeAOT-coreclr .NET runtime optimized for ahead of time compilation Epic Groups multiple user stories. Can be grouped under a theme. Priority:0 Work that we can't release without Team:Runtime
Projects
None yet
Development

No branches or pull requests