[HN Gopher] Native AOT Overview
       ___________________________________________________________________
        
       Native AOT Overview
        
       Author : luu
       Score  : 71 points
       Date   : 2023-05-24 17:25 UTC (2 days ago)
        
 (HTM) web link (ericsink.com)
 (TXT) w3m dump (ericsink.com)
        
       | galonk wrote:
       | I don't know how it works, but it seems very odd that
       | serialization/reflection wouldn't work with AOT... the
       | information you need is there in memory either way, isn't it?
        
         | reubenmorais wrote:
         | An explanation of the problem:
         | https://github.com/dotnet/corert/blob/master/Documentation/u...
        
         | dellamonica wrote:
         | It can get really tricky: using reflection you could read a
         | string from any input and create a generic type instantiation
         | that never happens in the source code. How would the code for
         | that type be present in an AOT scenario?
         | 
         | There are also several optimizations that can be made in AOT
         | compiled code that are not allowed when you enable unrestricted
         | reflection or dynamically loading code. As an example, suppose
         | an interface is implemented by just one type in your code. If
         | you AOT compile it, the compiler can safely assume that all
         | calls to methods on that interface actually go to that single
         | type implementing it, thus it can replace interface dispatches
         | with direct calls.
        
         | pjc50 wrote:
         | The default XML (de)serializer does a lot of code generation at
         | runtime. Which doesn't work with AOT.
        
         | MarkSweep wrote:
         | You can get serialization to work, but you have to use a
         | serialization framework that is trimming compatible. For
         | example, to use System.Text.Json, you have to opt-in the types
         | you want to serialize.
         | 
         | https://learn.microsoft.com/en-us/dotnet/standard/serializat...
        
           | sebazzz wrote:
           | "Opt-in" is not doing this feature justice, that is full
           | serialization code pre-generated at compile time for your
           | types. Beautiful.
        
       | jmillikin wrote:
       | I used to contribute to a C# project aimed at Linux users[0], and
       | one of the personally annoying aspects was requiring the .NET
       | runtime. It's a lot like how Java programs require a JVM, except
       | worse because OpenJDK is a blessed implementation in a way that
       | Mono never was.
       | 
       | When I saw that .NET 7 included AOT, I immediately downloaded it
       | to play around. It's clearly not fully baked (missing macOS
       | support), but what is there is _great_. AOT makes C# a direct
       | competitor to Go for projects that don 't need to wring every
       | last cycle out of the CPU, and it doesn't have the same
       | squeamishness about language complexity that characterizes Go.
       | 
       | The only part of .NET 7 that really bothers me is the compilation
       | process. I couldn't find any compile-to-obj command with flags
       | and such, instead there's a `dotnet` command that takes its input
       | via a monolithic `.csproj` XML file and spits out a fully-formed
       | binary. Trying to integrate C# into a Unix-style build pipeline
       | (make/Bazel) doesn't seem straightforward in the current SDK.
       | 
       | [0] https://www.banshee-project.org/
        
         | nerdix wrote:
         | Loved Banshee. There was a short period of time during the mid
         | 00s where it looked like Mono/C# had a chance to become the
         | dominate platform for gnome apps. Banshee, F-Spot, Beagle,
         | Docky.
         | 
         | And some really good stuff came out of the Mono as well. Like
         | Mono.Cecil
        
         | andygocke wrote:
         | > I couldn't find any compile-to-obj command with flags and
         | such, instead there's a `dotnet` command that takes its input
         | via a monolithic `.csproj` XML file and spits out a fully-
         | formed binary
         | 
         | FYI I'm the lead of the Native AOT team at MSFT.
         | 
         | The key thing about .NET AOT is that it compiles the whole
         | framework together, so right now the `dotnet` command is the
         | top-level tool that connects all the pieces together.
         | 
         | You're right that this can be complicated to integrate with
         | other build tooling. It's something we can work on, but there's
         | a bit of inherent friction around the .NET side, where it needs
         | to find all the appropriate libraries, NuGet packages, etc, and
         | a make/bazel world.
         | 
         | Definitely something we can work on as we go forward.
        
         | fabian2k wrote:
         | You don't even need native AOT for that, you can already create
         | self-contained binaries with .NET Core. Those have fewer
         | restrictions than native AOT, they bundle the necessary
         | runtime.
        
           | pjc50 wrote:
           | They have some annoying downsides: they _unpack_ the runtime
           | when you run them. This can cause problems like  "virus
           | scanner takes time looking at each .dll unpacked" and "fill
           | up the disk they're unpacked into".
           | 
           | If they don't fix this by version 8 I might have to build my
           | own CLR apphost solution :(
        
             | fabian2k wrote:
             | I don't think that is the case anymore. I think it also was
             | platform-specific before and only applied to Linux. But I
             | couldn't find the exact change with a quick search.
        
               | pjc50 wrote:
               | It's not the case for AOT, but it is for "self-
               | contained", at least as of .NET 6.
        
               | ripley12 wrote:
               | I believe this got fixed in .NET 5; now only native
               | libraries need to be extracted and stored elsewhere on
               | disk, and many applications can get by without native
               | dependencies.
               | 
               | > When the app starts, the managed DLLs are extracted and
               | loaded in memory, avoiding the extraction to a folder.
               | 
               | https://learn.microsoft.com/en-
               | us/dotnet/core/deploying/sing...
        
               | fabian2k wrote:
               | It doesn't extract onto disk, I'm not sure if it is still
               | doing some extraction into memory.
        
         | Nathanba wrote:
         | well nowadays you dont need to add each .cs file separately
         | into the csproj file anymore which means you can pretty much
         | just use the same file for your projects and the only
         | difference are the package references. It's not that far away
         | from a barebones folder but I really agree that the default
         | build should allow me to omit csproj files entirely
         | 
         | and then maybe even change the default build to always use AOT
         | and you're precisely where golang is
        
         | tempodox wrote:
         | I compile F# to a stand-alone executable that runs on a Linux
         | box without any additional .NET installs:
         | dotnet publish /property:PublishSingleFile=true
         | --configuration=Release --self-contained=true
        
         | rubenv wrote:
         | Fellow Banshee contributor, ex-F-spot maintainer here. Those
         | were good days.
        
           | sandyarmstrong wrote:
           | Yup, there was so much excitement around the free desktop as
           | a promising future for computing. I miss it! And I always
           | appreciated your contributions.
           | 
           | Now we all use unbelievably locked-down mobile devices,
           | nobody even knows what files and folders are, and fewer kids
           | than ever are able to learn about how computers work by
           | messing around under the hood. Other amazing things are
           | happening, but it's sad what gets lost.
        
         | Rochus wrote:
         | > _annoying aspects was requiring the .NET runtime ... OpenJDK
         | is a blessed implementation in a way that Mono never was_
         | 
         | Which is unjustified, because Mono CLR is just a single
         | executable less than 5 MB which you can download and run
         | without a complicated installation process (see e.g.
         | https://github.com/rochus-keller/Oberon/#binary-versions ). AOT
         | compilation on the other hand is a huge and complex
         | installation depending on a lot of stuff including LLVM, and
         | the resulting executables are not really smaller than the CLR +
         | mscorlib + app.
        
           | aseipp wrote:
           | Well, context and history is also probably relevant because
           | for a very long time there was a lot of (mostly unwarranted,
           | at least IMO) fear surrounding Mono and or not it was
           | something Microsoft would care about in the future (or other
           | random things verging on total conspiracy). Banshee is a
           | pretty long-lived project; we might be talking 10+ years ago.
           | These days I think it's pretty clear that both Mono and .NET
           | Core are reasonable and officially battle-tested options.
           | 
           | Anyway, I'm not sure what Mono's AOT compiler looks like
           | these days, but the new Native AOT for .NET (which is
           | improved in .NET 8) is definitely designed for production and
           | things like binary size and startup speed, with no external
           | dependencies, and they definitely seem to be trying to make
           | it act and feel like other natively compiled AOT languages.
           | People care more about it these days because a big shift is
           | in things like containerized runtimes where you don't want to
           | pay for the overhead of distributing the .NET runtime for
           | each container, because they can't be shared. So things like
           | AOT, dead code elimination, reflection removal for source
           | generators at build time etc all add up. Cold-start time is
           | also important for some of those uses.
           | 
           | Linux distro fragmentation and userspace ABI compatibility
           | being an afterthought also makes some FOSS/Linux projects
           | that require interpreters/runtimes more annoying than they
           | need to be and that also had some cultural, perceptive
           | ramifications for a long time too -- that's not really .NET
           | specific, but it probably never helped. Like, you're saying
           | "just download an executable and run it" but that was
           | actually often not workable in many cases for many reasons
           | for many apps. And whether or not whether users understand
           | what those reasons were, correctly or not, it colors their
           | perception of that class of tools.
           | 
           | But anyway. These days there are lots of solutions for these
           | problems. Native AOT is a pretty welcome solution for a good
           | class of issues IMO, and Mono and .NET Core both seem to be
           | established in various domains. I'll definitely be looking
           | forward to trying Native AOT on server-side apps.
        
             | jmillikin wrote:
             | > Banshee is a pretty long-lived project; we might be
             | talking 10+ years ago.
             | 
             | I looked through my archives and I think most of my
             | contributions were pre-2010, so 13+ years.
             | 
             | Mono was a very different thing back then -- less mature,
             | and Microsoft (mid Ballmer era) seemed to have a love/hate
             | relationship with it.
        
           | afavour wrote:
           | I think the most important part of the OP's complaint is
           | "blessed". For a very long time Mono was an entirely
           | unofficial reimplementation of .NET for Linux. You can't
           | blame anyone for being hesitant about relying on it.
        
             | Rochus wrote:
             | How can an implementation of a standard (ECMA-335 or ISO
             | 23271), which is even explicitly intended by MS to be used
             | by others (even supported by a comprehensive MS "open
             | source" implementation to illustrate it) be "entirely
             | unofficial"?
        
               | coredog64 wrote:
               | Been a while since I've touched the CLR, but I have this
               | vague recollection that while the Mono runtime is
               | blessed, it's also incomplete. If you want to write a
               | portable CLI you can use Mono, but if you want to show a
               | GUI, you're out of luck.
        
               | Rochus wrote:
               | > _if you want to show a GUI, you're out of luck._
               | 
               | Mono included a powerful GUI framework which run on far
               | more platforms than the .NET GUI. And Ximian/Xamarin
               | invested a lot of effort to be as compatible as possible
               | to all aspects of .NET (see e.g. https://www.mono-
               | project.com/docs/about-mono/compatibility/).
        
               | senko wrote:
               | Because the standard wasn't enough to build a complete
               | app - parts are (were?) missing.
               | 
               | It was also _not_ explicitly intended, blessed or even
               | recognized by MS for a number of years. It was just
               | another open source project.
               | 
               | This gave rise to other platforms that were attempting to
               | improve on C (GNOME) / C++ (KDE), such as D, and finally
               | JavaScript for GNOME. Meanwhile, web apps (and then
               | Electron apps) became de-facto defaults due to their
               | cross-platform nature.
               | 
               | Had MS embraced (err...in a positive way!) Mono from the
               | start, taking into consideration Miguel's influence in
               | the GNOME community, GNOME 3 might have been written in
               | .NET.
        
               | Rochus wrote:
               | The standards cover the CLR and core library, i.e. the
               | stuff which is replaced in case of an AOT compiler. The
               | .NET framework is an implementation on top of CLR and the
               | core library, and the Mono project included a version
               | with the intention to be as compatible as possible to
               | .NET, but also an alternative, cross-platform framework,
               | which was/is suitable to build all kinds of applications,
               | including GUIs. Concerning the "blessing" I don't
               | understand why people are less concerned with JDK than
               | with Mono, because the owner of the technology is not
               | exactly known for not enforcing his rights in court (see
               | e.g. https://en.wikipedia.org/wiki/Google_LLC_v._Oracle_A
               | merica,_....). But fortunately there are limits to
               | copyright when it comes to compatibility.
        
         | MarkSweep wrote:
         | The .NET SDK has some options to integrate NativeAOT with a
         | larger application. You can reference libraries (static or
         | dynamic) and object files during the build to link into the
         | final executable. You can also configure NativeAOT to generate
         | a static or dynamic library that you can link into another
         | executable.
         | 
         | https://learn.microsoft.com/en-us/dotnet/core/deploying/nati...
        
           | jmillikin wrote:
           | Notice how that page describes how to configure the toolchain
           | using XML. That's the thing I don't like -- instead of just
           | building up an args list like cl.exe, I need to write my own
           | intermediate tooling that synthesizes a .csproj and spits it
           | out into the build sandbox before launching their magic do-
           | everything binary.
           | 
           | There's clearly something else underneath, the <LinkerArg>
           | element is exactly what I would want to generate when running
           | link.exe, but most of the configuration options are wrapped
           | in a layer of gunk.
           | 
           | Ideally it would be possible to invoke a command directly to
           | convert a bunch of *.cs files into a .dll (or .a), then I
           | could use existing logic to link it with link.exe (or ld).
        
             | pjc50 wrote:
             | FWIW, the relevant gunk: C:\Program Files\dotnet\sdk\7.0.10
             | 0\Sdks\Microsoft.DotNet.ILCompiler\build\Microsoft.NETCore.
             | Native.targets
             | 
             | And C:\Program Files\dotnet\sdk\7.0.100\Sdks\Microsoft.DotN
             | et.ILCompiler\build\Microsoft.NETCore.Native.Unix.targets
             | (where the linker is selected)
             | 
             | See the area around and after this chunk
             | <CustomLinkerArg Include="&quot;$(NativeObject)&quot;" />
             | <CustomLinkerArg Include="-o &quot;$(NativeBinary)&quot;"
             | Condition="'$(TargetOS)' != 'windows'" />
             | <CustomLinkerArg Include="/OUT:&quot;$(NativeBinary)&quot;"
             | Condition="'$(TargetOS)' == 'windows'" />
             | <CustomLinkerArg Include="/DEF:&quot;$(ExportsFile)&quot;"
             | Condition="'$(TargetOS)' == 'windows' and $(ExportsFile) !=
             | ''" />           <CustomLinkerArg Include="/LIBPATH:&quot;%
             | (AdditionalNativeLibraryDirectories.Identity)&quot;"
             | Condition="'$(TargetOS)' == 'windows' and
             | '@(AdditionalNativeLibraryDirectories->Count())' &gt; 0" />
             | <CustomLinkerArg Include="-exported_symbols_list
             | &quot;$(ExportsFile)&quot;" Condition="'$(TargetOS)' ==
             | 'OSX' and $(ExportsFile) != ''" />
             | <CustomLinkerArg Include="-Wl,--version-
             | script=$(ExportsFile)" Condition="'$(TargetOS)' !=
             | 'windows' and '$(TargetOS)' != 'OSX' and $(ExportsFile) !=
             | ''" />           <CustomLinkerArg
             | Condition="Exists('$(_Win32ResFile)')"
             | Include="&quot;$(_Win32ResFile)&quot;" />
             | <CustomLinkerArg Include="@(LinkerArg)" />
        
         | neonsunset wrote:
         | Self-contained single-file assemblies do not require this.
         | Simply specify corresponding properties in .csproj or as
         | arguments to dotnet publish (-p:PublishSingleFile=true --self-
         | contained -r {RID}) and for pure C# projects you will get
         | exactly a single executable file that does not require any
         | dependencies to run except what is expected to have on the
         | average target system (glibc, openssl, etc.).
         | 
         | Other than that, it seems that due to other languages, there is
         | misconception that Native AOT is a panacea that is superior in
         | all areas to normal single-file executables that use JIT. In
         | fact, on average, JIT produces faster code because some
         | optimizations are only possible with tiered and dynamic PGO
         | compilation.
        
         | aseipp wrote:
         | I've been wondering how to integrate modern .NET Core into a
         | custom build system (buck2) and was wondering similar things.
         | There's this project I think is cool called bflat[1] that
         | basically makes the C# compiler more like the Go compiler in
         | the sense it's a one-shot single-use tool that can cross
         | compile binaries natively. It's done by one of the people on
         | the .NET Runtime team as a side project, and quite neat.
         | 
         | I mostly use Visual Studio but I _think_ in practice you 're
         | supposed to compile whole .dll's or assemblies all at once,
         | which acts as the unit of compilation; I don't think the csharp
         | compiler generates native object-files-for-every-.cs or
         | translation unit, the kind of approach you'd expect from javac
         | or g++. Someone please correct me if I'm wrong though! I'd like
         | to learn more if there's a more granular/incremental unit of
         | compilation.
         | 
         | Since Roslyn and the compiler itself are mostly a library,
         | maybe you could also write your own custom "csc-for-bazel"
         | compiler or something to sort of bootstrap the whole thing and
         | offer tighter integration...
         | 
         | .NET 8 will support Native AOT on macOS, I think.
         | 
         | [1] https://github.com/bflattened/bflat
        
           | andygocke wrote:
           | .NET 8 will support macOS, and yeah I think your approach of
           | basically re-implementing much of the SDK logic in bazel is
           | probably your best bet for a reliable experience.
           | 
           | At the same time, it's obvious that that's a considerable
           | chunk of work.
           | 
           | Also, IDEs like VS and VS Code are reliant on MSBuild APIs to
           | construct a semantic understanding of the projects, so
           | without MSBuild files, they won't properly function.
           | 
           | This is an unfortunate problem, which I don't have a simple
           | solution for.
        
           | MarkSweep wrote:
           | For more incrementalism, you can tell csc to generate
           | reference assemblies. These assemblies contain only the
           | public surface area of the assembly. You can use them to
           | avoid recompiling downstream assemblies when the public API
           | surface does not change. They are similar to ijars in Java.
           | 
           | https://learn.microsoft.com/en-
           | us/dotnet/standard/assembly/r...
           | 
           | I've been thinking a lot about what a good intervention of
           | .NET and tools like Buck would look like. I think both Buck 1
           | and Bazel's rules_dotnet directly target the csc compiler.
           | Given how much logic is written in MSBuild files and how many
           | steps are part of the build (analyzers, illink, ilcompiler),
           | I think it makes sense to target the dotnet executable
           | directly. Having a way to set arbitrary MSBuild properties
           | and items would be nice.
           | 
           | It would be nice if you could generate Visual Studio projects
           | from the Buck targets.
           | 
           | Lastly, it would be nice if these rules supported Bazel-style
           | persistent workers. Both MSBuild and csc support a client
           | server architecture, but rules_dotnet does not take advantage
           | of that currently. Performance suffers accordingly.
        
         | pjc50 wrote:
         | > Trying to integrate C# into a Unix-style build pipeline
         | (make/Bazel) doesn't seem straightforward in the current SDK.
         | 
         | Basically, don't do that. "dotnet build" invokes "msbuild"
         | which _is_ a build system analogous to make. If you want a
         | remotely peaceful life, just lay out the project the way
         | Microsoft expect you to and let it do its thing.
         | 
         | You can invoke Roslyn "csc" from the command line, but some of
         | the more obscure bits of tooling (e.g. building "self
         | contained" executables) are only implemented as .dlls that are
         | msbuild Task objects.
         | 
         | Msbuild isn't too bad once you've got over the culture shock
         | that (a) everything is XML rather than tab-delimited makefiles
         | and (b) you've got a glossary of terms that maps to things you
         | know https://learn.microsoft.com/en-
         | us/visualstudio/msbuild/msbui... and (c) you get the binary log
         | viewer https://msbuildlog.com/, which is a fantastic tool that
         | gives you total observability of every detail of the build
         | process. Of which there is a lot.
         | 
         | Separate thought: .net AOT is still very much experimental. All
         | sorts of things are silently incompatible with it, either in
         | the "refuses to build" or the "crash at runtime" way. I'd only
         | use it for small projects built from the ground up to be AOT.
        
           | andygocke wrote:
           | > Separate thought: .net AOT is still very much experimental.
           | All sorts of things are silently incompatible with it, either
           | in the "refuses to build" or the "crash at runtime" way. I'd
           | only use it for small projects built from the ground up to be
           | AOT.
           | 
           | It's certainly true that most things aren't AOT-compatible
           | out of the box -- this is basically due to the heavy
           | ecosystem reliance on reflection.
           | 
           | BUT, it definitely shouldn't be _silently_ incompatible. We
           | 've spent a lot of time building "trimming warnings"
           | (https://learn.microsoft.com/en-
           | us/dotnet/core/deploying/trim...) that should flag any and
           | all incompatibilities.
           | 
           | If there's some incompatibility, a warning should be
           | generated. If there isn't that's likely a bug on us
           | (https://github.com/dotnet/runtime). But conversely, if there
           | are no warnings, you should be guaranteed that the app should
           | be AOT-compatible.
        
           | jmillikin wrote:
           | I'm satisfied with Bazel as a build system, and some of its
           | functionality that is important to me (sandboxed remote
           | execution) works best when it's not used to delegate to
           | recursively nested sub-builds. To the extent I wish anything
           | different about Bazel, it's to move even further away from
           | integrated language-specific logic[0].
           | 
           | The idea of trying to learn some new ecosystem-specific build
           | tool (in this case msbuild) is unappealing. Done that too
           | many times, and I'm tired of fighting with tools written
           | for/by people who think projects are written in a single
           | language.
           | 
           | [0] I hear Buck2 is a step in this direction.
        
             | iainmerrick wrote:
             | I've been burned by using the original Buck in an app which
             | is now a pain to maintain. It looks like Bazel is the best
             | path for me to get free of it.
             | 
             | I looked briefly at Buck2 but it doesn't work yet (for my
             | purposes, at least). Facebook have copied the old Google
             | cliche, "you can use the old version that's deprecated, or
             | the new version that doesn't work yet".
             | 
             |  _Edit to add:_ a million times yes to your general point!
             | Language-specific build systems are bad.
        
           | anarazel wrote:
           | > Msbuild isn't too bad once you've got over the culture
           | shock that (a) everything is XML rather than tab-delimited
           | makefiles and (b) you've got a glossary of terms that maps to
           | things you know https://learn.microsoft.com/en-
           | us/visualstudio/msbuild/msbui... and (c) you get the binary
           | log viewer https://msbuildlog.com/, which is a fantastic tool
           | that gives you total observability of every detail of the
           | build process. Of which there is a lot.
           | 
           | I've only had to interact with it for C[++], but based on
           | that, I'd do a lot to not use it for projects I work on. No-
           | action-needed builds are orders of magnitude slower than with
           | any other tool, the determination of what needs to be rebuilt
           | is ... not accurate, understanding the build rules is hard,
           | there is very little useful documentation, there are a lot of
           | bugs.
        
       | ducharmdev wrote:
       | I didn't realize macOS wasn't supported, that's a disappointment.
       | I work at a startup that's all .NET 6 on macbooks, and I was
       | pretty excited at the chance to use native AOT.
       | 
       | I assume running an app in a container wouldn't allow you to
       | sidestep that problem?
        
         | neonsunset wrote:
         | A change to support macOS just barely missed the snap to get in
         | .NET 7 but has been available since early pre-preview builds of
         | .NET 8. Its support is really good in 8 and there will be even
         | a feature to use NativeAOT for 'net8.0-ios' targets meaning you
         | could write components in C# and integrate them into Swift
         | binaries via C bindings (maybe there are better interop
         | options? my knowledge is very limited on this topic).
        
         | kryptiskt wrote:
         | If you want to be on the bleeding edge, the .NET 8 previews
         | supports AOT for macOS.
        
           | ericsink wrote:
           | Indeed. I've been using the .NET 8 previews with Native AOT
           | on an M1 Mac for several weeks, and things work quite nicely.
        
             | ducharmdev wrote:
             | Oh sweet, I'll probably wait for November when .NET 8
             | releases but good to know it works well on the M1!
        
       | lowleveldesign wrote:
       | NativeAOT is an excellent way to expose .NET code to native apps.
       | One big feature I am missing is support for x86. If you have a
       | 32-bit app in which you want to inject your .NET library,
       | NativeAOT won't help.
        
       | ericsink wrote:
       | (Author here)
       | 
       | Most of the buzz about .NET Native AOT is focused on things like
       | startup time for compiled executables in cloud environments. For
       | good reason.
       | 
       | But Native AOT also supports compilation to libraries with a C
       | ABI, including both shared libs and static. My blog series tends
       | to lean in that direction, talking about interoperability.
       | 
       | Some of the posts talk about very fundamental things. Some of the
       | later posts give mention to a (somewhat experimental) binding
       | generator I've been working on, using CLR metadata to
       | automatically create glue and projections for other languages
       | like Rust and TypeScript.
       | 
       | In general, interop between C# and other languages has been
       | possible for a long time, but Native AOT allows it to be done
       | without hosting a CLR, and as the feature matures, I think
       | that'll make it more interesting for some use cases.
        
       | Mertax wrote:
       | How do serialization libraries, like Newtonsoft JSON.net, work on
       | platforms like iOS/Blazor/Unity that use AOT? Doesn't seem like
       | anything special has to be done other than reference the Nuget
       | package and it's just working?
        
         | matthew-wegner wrote:
         | With Unity/IL2CPP stuff: For general-purpose serialization
         | libraries like JSON, you sometimes need to provide hints to
         | make sure types are included:
         | https://github.com/jilleJr/Newtonsoft.Json-for-Unity/wiki/Fi...
         | 
         | For schema serialization on known types, there are codegen
         | tools (i.e. moc for MessagePack):
         | https://github.com/neuecc/MessagePack-CSharp
         | 
         | MessagePack is migrating to Rosalyn code generators, so
         | basically invisible codegen. Cysharp's newer serialization
         | library, MessagePack, already uses this:
         | https://github.com/Cysharp/MemoryPack
        
           | Nathanba wrote:
           | memorypack looks interesting but the page omits a payload
           | size comparison so who knows how good it really is
        
         | ledgerdev wrote:
         | I was able to use aot and System.Text.Json in a test app. You
         | only need to put an attribute on a class to specifying the type
         | info, and then pass a type enum when you serialize/deserialize.
         | I was surprised how easy it was because I had been really
         | concerned about reflection based stuff like json.
        
         | dellamonica wrote:
         | There has been a push for using Source Generators to move stuff
         | that relies on reflection to compile time code generation. JSON
         | serialization is (mostly) supported in this mode with perf
         | advantages as well.
         | 
         | This does not address pre-existing packages obviously. To make
         | them work with AOT you might need to include an XML file
         | (rd.xml) that indicates all the types that could be dynamically
         | generated in your code. It is quite brittle and AFAIK
         | everything might work until you get a runtime failure if
         | something you did not include ends up being constructed.
        
           | GordonS wrote:
           | And when stuff does inevitably break once deployed to
           | production, it can be _really_ difficult to pinpoint the
           | reason _why_.
           | 
           | I've stopped using AOT, as IMO it's not (currently) suitable
           | for complex, real-world apps - unless you are prepared for a
           | lot of testing and pain.
        
         | kryptiskt wrote:
         | As I understand it, Mono supports reflection when compiling
         | AOT, so serializing using reflection would work.
         | 
         | With a newish .NET they don't need reflection for AOT code, as
         | JSON libraries can use source generators instead.
        
       | zerr wrote:
       | Does it support any of WinForms/WPF/WinUI3/MAUI or is it just for
       | CLI apps?
        
         | ericsink wrote:
         | None of those are working yet. I'm hoping to get things going
         | with MAUI.
         | 
         | But I've made some progress with Avalonia.
         | 
         | Here's a sample using Native AOT and Avalonia, with a
         | projection to Rust:
         | 
         | https://github.com/sourcegear/bridge-info/tree/main/samples/...
         | 
         | And here's (basically) the same sample projected to TypeScript:
         | 
         | https://github.com/sourcegear/bridge-info/tree/main/samples/...
         | 
         | These are built using the binding generator I mentioned
         | elsewhere in the comments here. All this stuff is just raw
         | tech, not a ready-to-use solution.
        
       | dhosek wrote:
       | I was just thinking that if Microsoft were Apple, they'd just
       | design a chip so that the IL code would be native code. I've
       | often wondered what it would take for .net's IL (or Java Byte
       | Code) to be the native instruction set of a processor.
        
       | SillyUsername wrote:
       | What goes around comes around.
       | 
       | 2000s Compile to binary > bytecode (performance, size and startup
       | time important)
       | 
       | 2010s Compile to bytecode > binary (performance important)
       | 
       | 2020s Compile to binary > bytecode (size and startup time
       | important).
        
       | garganzol wrote:
       | Not really useful because nothing works except the simplest apps.
       | I understand that it is possible to "dumbdown" the code in order
       | to make it work with AOT, but it is too much hassle to even try.
       | 
       | So, while it was released as a non-experimental feature, actually
       | it still is.
        
       | weinzierl wrote:
       | Every couple of years I look into Java AOT and it always has been
       | awful so far. I wonder if C# will be the same or if they manage
       | to get it right.
        
         | brabel wrote:
         | The current way to compile Java AOT is GraalVM's native-
         | image... that actually works pretty well... do you find that
         | awful??
        
           | weinzierl wrote:
           | It looks promising, but so did gcj at its time.
           | 
           | Still it's not practically usable and that's what counts for
           | me. From what I understand it is plagued with the same issues
           | as the C# AOT when it comes to reflection and therefore
           | serialization. There is a whole list of other issues as
           | well[1].
           | 
           | I think some of this issues can never be solved by the
           | compiler alone but need to be addressed in the ecosystem. It
           | would be important, for example, that the most common and
           | important libraries dispense with reflection to play well
           | with AOT.
           | 
           | Finally GraalVM is just a single project with its own
           | specific agenda. If Oracle changes its mind about these goals
           | tomorrow Java AOT will be dead once again.
           | 
           | These are the reasons I'm still not optimistic about Java
           | AOT, even if GraslVM is really cool project.
           | 
           | [1] https://www.graalvm.org/22.0/reference-manual/native-
           | image/L...
        
             | CuriousSkeptic wrote:
             | They are addressing reflection rather aggressively
             | actually, using source generators mostly.
             | 
             | Even if I have no direct need for AOT I'm eager for the
             | added type safety and sanity gained by getting rid of
             | reflection, not least for serialisers!
        
         | neonsunset wrote:
         | There are efforts to ensure that important workloads like
         | ASP.NET Core work with it well. Due to AOT nature it's often
         | not possible to make it require just a build argument switch,
         | but it is still fairly easy nonetheless, in 90% of situations
         | having to do with switching from reflection to source
         | generation (like in the case of System.Text.Json) or solving
         | statically not-analyzable patters of reflection (AOT supports
         | reflection, just not emitting new code in runtime since there's
         | no JIT!).
         | 
         | Well-written libraries that do not use reflection to generate
         | new code in runtime do not require any changes and "just work".
         | A lot of new code shipped is now written with Native AOT in
         | mind to be compatible (with some exceptions, looking at you,
         | SemanticKernel).
        
       ___________________________________________________________________
       (page generated 2023-05-26 23:01 UTC)