ScottArbeit / Grace

Grace Version Control System

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Figure out correct settings for Native AOT build

ScottArbeit opened this issue · comments

Right now, I'm testing Grace CLI using .NET's Ready To Run (R2R) feature, which emits pre-JITted code to run. That means that instead of waiting for the .NET CLR to JIT the code at runtime, we provide a fast-to-start JIT implementation in the .dll, and allow the .NET runtime to do further hot-path recompilation as it decides it should.

The R2R version has a few-hundred-millisecond delay in getting started, owing to getting the CLR going before running Grace itself. It's fine for now, but it's not what I want to ship with.

.NET 7 has a Native Ahead-of-Time (AOT) compilation feature. This builds the entire application including the CLR, trims unused .dll's and even unused individual methods, and emits a single, native executable file that starts instantly.

I tried a .NET 7 Native AOT build for Grace.CLI on 29-Dec-2022, and it failed. I assume it's because there were issues during trim; we probably need to prevent it from trimming things having to do with actors, but that's just a guess.

If it's easy to include AOT for Grace Server, great, R2R is fine for it, .NET will recompile the hot-paths and the server will be at top speed fairly quickly in production.

Now that .NET 8 has been released, Native AOT is a thing... for C#.

I've seen the work that the .NET team did to find places that the CLR and BCL were using Reflection and dynamic code generation, and replace them with C# source generators and C# interceptors.

As of November 2023, F# doesn't have source generators (there's an open issue). Until we do, native AOT is going to be out-of-reach for F#. And I'm OK with that (for now).

For Grace.Server, compiling with <PublishReadyToRun>true</PublishReadyToRun> for Release builds will give us fast start-up, and still allow for Dynamic Profile-Guided Optimization (PGO) for maximum performance. For Debug builds, I use <PublishReadyToRun>false</PublishReadyToRun> to make compiling faster.

I don't care if Grace.Server is ever compiled with Native AOT, it's just not important.

For Grace.CLI, though... I wish we had Native AOT, but we don't yet. I always build it <PublishReadyToRun>true</PublishReadyToRun> to get the closest sense I can to how fast we can make it. It's annoying that there's always the ~300ms startup time for the .NET CLR before Grace starts running.

And, for now, Grace itself uses .NET Reflection in some important places, and those uses would have to be rewritten somehow to enable Native AOT. I have some ideas of how we might do that where we replace C# source generators with an orchestration that would call OpenAI services to inspect and generate source code during build. When it's important, we can revisit, and by then it'll probably be even easier.

For now, I'm going to close the Native AOT exploration. We won't revisit it until F# source generators are a thing.