Skip to content

Commit 8c60389

Browse files
committed
a couple edits
1 parent 068bc90 commit 8c60389

File tree

2 files changed

+9
-7
lines changed

2 files changed

+9
-7
lines changed

.jekyll-metadata

0 Bytes
Binary file not shown.

_posts/2024/2024-02-01-native-aot.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,25 @@ I don't even know how to begin this post. I don't think there has been as big a
1010

1111
***HUGE*** thanks to [Jevan Saks](https://github.com/jevansaks) for the help on this. This update wouldn't be possible without him. Saying he coded half of the update would be underselling his contributions! More than code, though, he helped me better understand what all of this AOT stuff is and the APIs that make it work.
1212

13-
Additional thanks to Eirik Tsarpalis, who basically **is** _System.Text.Json_ right now, for helping shed light on intended patterns with serializer contexts.
13+
Additional thanks to [Eirik Tsarpalis](https://github.com/eiriktsarpalis), who basically **is** _System.Text.Json_ right now, for helping shed light on intended patterns with JSON serializer contexts.
1414

1515
## What is Native AOT?
1616

17-
[Native AOT](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/), or _Ahead of Time_ compilation, is a way to make .Net applications run anywhere using native code. That means they don't need the runtime to operate.
17+
[Native AOT](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/), or _Ahead of Time_ compilation, is a way to make .Net applications run anywhere using native code, which means they don't need the runtime to operate.
1818

1919
What that means for developers who want to _make_ native apps is generally avoiding dynamically generated code, so mostly no JIT (just-in-time compilation) or reflection that involves generics. You can start to imagine how limiting that can be. It makes things especially difficult for operations like serialization, which traditionally relies heavily on reflection.
2020

2121
However, the _System.Text.Json_ team is pretty smart. They've figured out that they can use source generation to inspect any code that might be serialized and generate code that stores the type information, all at compile time. But they can't do that without your help.
2222

23-
First, you have to mark your project as AOT-compatible (the source generation stuff can be done outside of AOT). Then you have to set up a serializer context and annotate it with attributes for every type that you expect to serialize. This is the trigger for the source generation. Lastly, any usage of a method which uses unsupported reflection will generate a compiler warning, and then you have some attributes that you can use to either pass the warning on to your callers or indicate that you understand the risk.
23+
First, you have to mark your project as AOT-compatible (the source generation stuff can be done outside of AOT). Then you have to set up a serializer context and annotate it with attributes for every type that you expect to serialize. (This is the trigger for the source generation.) Lastly, any usage of a method which uses unsupported reflection will generate a compiler warning, and then you have some attributes that you can use to either pass the warning on to your callers or indicate that you understand the risk.
2424

2525
Of course there's a lot more to understand, and I don't claim that I do. So go read the .Net docs or a blog post that focuses more on the power of Native AOT to learn more.
2626

2727
## Why support .Net 8 explicitly?
2828

2929
My understanding was that there were a lot of features in .Net 8 that I didn't have access to when building only to .Net Standard 2.0. Primarily, the compiler only gives the AOT warnings when building for .Net 8. Since that was the goal, it made sense to include the target explicitly.
3030

31-
What was unclear to me was that the majority of the features that I wanted to use were actually in available through either later versions of the _System.Text.Json_ Nuget package or through [Sergio Pedri
31+
What was unclear to me was that the majority of the features that I wanted to use were actually available through either later versions of the _System.Text.Json_ Nuget package or through [Sergio Pedri
3232
](https://github.com/Sergio0694)'s amazing [PolySharp](https://github.com/Sergio0694/PolySharp) package.
3333

3434
> I had at some point tried to update to _System.Text.Json_ v7, but I found that a good portion of the tests started failing. I didn't want to deal with it at the time, so I put it off.
@@ -38,7 +38,9 @@ What was unclear to me was that the majority of the features that I wanted to us
3838

3939
I've had a [long-standing issue](https://github.com/gregsdennis/json-everything/issues/390) open on GitHub where I considered the possibility of dropping .Net Standard support and moving on to just supporting one of the more modern .Net versions. In that issue, I floated the idea of updating to .Net 6.
4040

41-
While that issue languished for almost a year, I had users approach me about supporting features that were only supported in later versions of frameworks. That meant that I'd have to multi-target. I've multi-targeted in libraries before, and I've seen in other libraries the code reading nightmare that can result from a bunch of compiler directives trying to isolate features that were only available in different .Net versions. Trying to read through all of that to isolate what's actually compiling under a given framework target can be tough.
41+
While that issue languished for almost a year, I had users approach me about supporting features that were only available in later versions of frameworks, which meant that I'd have to multi-target.
42+
43+
I've multi-targeted in libraries before, and I've seen in other libraries the code-reading nightmare that can result from a bunch of compiler directives trying to isolate features that were only available in different .Net versions. Trying to read through all of that to parse out what's actually compiling under a given framework target can be tough.
4244

4345
The springboard for this effort really came from Jevan's jumping into the deep end and starting the update by creating a PR. This was the kick in the pants I needed.
4446

@@ -55,11 +57,11 @@ We started updating all of the package references and addressing the immediate w
5557

5658
Then we added `<IsAotCompatible>` properties to all of the library project files, which gave us our first round of AOT warnings to address.
5759

58-
We went through almost 40 PRs between Jevan and me, incrementally updating toward a final state. There was a lot of experimentation and discussion over patterns, and I learned a lot about the AOT APIs as well as finding some solutions to a few pitfalls.
60+
We went through almost 40 PRs between Jevan and me, incrementally updating toward a final state. There was a lot of experimentation and discussion over patterns, and I learned a lot about the AOT APIs as well as finding some solutions to a few pitfalls. I can't tell you how many approaches and workarounds we added only for them to ultimately be removed in favor of something else. But it was part of the learning process, and I don't know that we could have reached the final solution without going through the alternatives.
5961

6062
It wasn't all adding code, though. Some of the functionality, like the `JsonNode.Copy()` extension method wasn't needed anymore because the updated _System.Text.Json_ provides a `.DeepClone()` that does the same job.
6163

62-
By the end of it we were left with just about everything supporting Native AOT. And, mostly thanks to PolySharp, we didn't need to litter the code with compiler directives. The only project that explicitly doesn't work in an AOT context is the schema generation, which requires high levels of reflection to operate. (But really, I consider that to be more for development tools rather than a production library; it's supposed to give you a start.)
64+
By the end of it we were left with just about everything supporting Native AOT. And, mostly thanks to PolySharp, we didn't need to litter the code with compiler directives. (I was even able to remove the dependency on _Jetbrains.Annotations_!) The only project that explicitly doesn't work in an AOT context is the schema generation, which requires high levels of reflection to operate. (But really, I consider that to be more for development tools rather than a production library; it's supposed to give you a start.)
6365

6466
## Is there anything to watch out for when updating to the new packages?
6567

0 commit comments

Comments
 (0)