Skip to content
Ian Griffiths By Ian Griffiths Technical Fellow I
How .NET 9.0 boosted AIS.NET performance by 9%

TLDR; .NET 9.0 increased performance in our Ais.NET library by 9% with no code changes. Performance has doubled since .NET Core 3.1. A Surface Laptop Studio 2 can process 9.95 million messages per second!

At endjin, we maintain Ais.Net, an open source high-performance library for parsing AIS messages (the radio messages that ships broadcast to report their location, speed, etc.). Each time a new version of .NET ships, we check it all still works and then run our benchmarks again. Each year, we've seen significant improvements:

So what about .NET 9.0? The short answer is that yet again it is significantly faster. For continuity I have run the benchmarks on the same desktop computer as when I first started benchmarking this library, meaning these figures are all directly comparable.

For the fourth year running, we're enjoying a substantial free lunch! Without making any changes whatsoever to our code, our benchmarks improved by roughly 9% simply by running the code on .NET 9.0 instead of .NET 8.0. As with last time, we've not had to release a new version—the existing version published on NuGet (which targets netstandard2.0 and netstandard2.1) runs faster just as a result of upgrading your application to .NET 9.0.

The Introduction to Rx.NET (v6.1) 3rd Edition (2025) Book, by Ian Griffiths & Lee Campbell, is now available to download for FREE.

Our memory usage has come down a little. Our amortized allocation cost per record continues to be 0 bytes. The total memory usage including startup costs is very similar: a handful of kilobytes, depending on exactly which features you use.

Benchmark results

We have two benchmarks. One measures the maximum possible rate of processing messages, while doing as little work as possible for each message. This is not entirely realistic, but it's useful because it establishes the upper bound on how fast an application can process AIS messages on a single thread. The second benchmark uses a slightly more realistic workload, inspecting several properties from each message. Each benchmark runs against a file containing one million AIS records.

.NET 6.0

When I tested on .NET 6.0 in January 2022, I saw the results shown in this next table when running the benchmarks on my desktop. These figures correspond to an upper bound of 3.8 million messages per second, and a processing rate of 3.1 million messages a second for the slightly more realistic example. (The desktop I've run all these benchmarks on is now about 7 years old, and it has an Intel Core i9-9900K CPU.)

Method Mean Error StdDev Allocated
InspectMessageTypesFromNorwayFile1M 262.9 ms 3.21 ms 2.84 ms 5 KB
ReadPositionsFromNorwayFile1M 322.8 ms 4.50 ms 3.99 ms 7 KB

.NET 7.0

Running the same benchmarks on .NET 7.0 gave us about 4.7 million messages per second for the very basic case and 3.7 million per second for the more realistic one:

Method Mean Error StdDev Allocated
InspectMessageTypesFromNorwayFile1M 213.8 ms 4.25 ms 4.55 ms 4 KB
ReadPositionsFromNorwayFile1M 267.9 ms 3.74 ms 3.31 ms 5 KB

.NET 8.0

These were the numbers for .NET 8.0. The upper bound is 5.72 million messages per second, and the more realistic example processes 4.75 million messages per second.

Method Mean Error StdDev Allocated
InspectMessageTypesFromNorwayFile1M 174.7 ms 2.20 ms 2.06 ms 4 KB
ReadPositionsFromNorwayFile1M 210.5 ms 4.15 ms 4.08 ms 5 KB

I repeated these tests just now on the very latest .NET 6.0 and .NET 7.0, and .NET 8.0 runtimes. (Only .NET 8.0 remains in support, but I wanted to check that the host machine wasn't misbehaving.) Within the bounds of experimental noise, the results were essentially the same. (That's what you'd hope, given that this is running on the same hardware, but the .NET runtime does get regular updates, so it's worth checking performance has remained the same on those versions.)

.NET 9.0

And now, the .NET 9.0 numbers:

Method Mean Error StdDev Allocated
InspectMessageTypesFromNorwayFile1M 156.7 ms 1.04 ms 0.97 ms 4.13 KB
ReadPositionsFromNorwayFile1M 192.3 ms 1.33 ms 1.18 ms 4.13 KB

This shows that on .NET 9.0, our upper bound moves up to 6.38 million messages per second, while the processing rate for the more realistic example goes up to 5.20 million messages per second. Those are improvements of 11% and 9% respectively on .NET 8.0. (I put the smaller 9% figure in the blog title because that benchmark better represents what a real application might do. I've done this in previous years regardless of which of the 2nd benchmarks showed the larger of the two increases.)

Surface Laptop Studio 2

You might be wondering where the 9.95 million messages per second figure in the opening paragraph came from. That's from running the same benchmark on newer hardware. I use my old desktop to get a consistent view of performance changes over time, but it understates what's possible on current hardware. Here are the numbers from my laptop (a Surface Laptop Studio 2 with a 13th gen Intel Core i7-13800H):

Method Mean Error StdDev Allocated
InspectMessageTypesFromNorwayFile1M 100.5 ms 0.77 ms 0.68 ms 3.87 KB
ReadPositionsFromNorwayFile1M 114.5 ms 0.97 ms 0.91 ms 3.86 KB

That gives us 9.95 million messages per second for the basic inspection, and 8.73 million messages per second with the more realistic workload.

Free performance gains over time

The bottom line is that just as moving your application onto .NET 8.0 may well have given you an instant performance boost with no real effort on your part (as did moving to .NET 7.0, before that, and .NET 6.0 before that) you may enjoy a similar boost upgrading to .NET 9.0.

We've been running these benchmarks across 6 versions of .NET now (.NET Core 2, .NET Core 3.1, .NET 6.0, .NET 7.0, .NET 8.0, and .NET 9.0,) enabling us to visualize how performance has improved across these releases for our library. First we'll look at the time taken to process 1 million AIS messages:

And next, the throughput in AIS messages per second (same benchmarks, just a different way to present the results):

Over the time the AIS.NET library has existed, performance has improved by well over double, thanks entirely to improvements in the .NET runtime!

Learn more about AIS.NET

You can learn more about our Ais.Net library at the GitHub repo, http://github.com/ais-dotnet/Ais.Net/ and in the same ais-dotnet GitHub organisation you'll also find some other layers, as illustrated in this diagram:

A diagram showing the Ais.Net library layering as three rows. The top row provides this description of Ais.Net.Receiver: AIS ASCII data stream ingestion using IAsyncEnumerable. Decoded message available via IObservable. The second row provides this description of Ais.Net.Models: Immutable data structures using C# 9.0 Records. Interface expose domain concepts such as position. The third row provides this description of Ais.Net: high performance, zero-allocation decode using Span<T>. ~3 million messages per second per core.

Note that there is a separate repository for Ais.Net.Models. And there's another for the Ais.Net.Receiver project. If you would like to experiment with this library, you will find some polyglot notebooks illustrating its use at https://github.com/ais-dotnet/Ais.Net.Notebooks

FAQs

How much faster is AIS.NET on .NET 9.0 compared to .NET 8.0? The AIS.NET library runs approximately 9% faster on .NET 9.0 for the realistic benchmark, with message processing rates increasing from 4.75 million messages per second to 5.20 million messages per second.
Do I need to update my AIS.NET code to benefit from .NET 9.0 performance improvements? No code changes are required. The existing AIS.NET version published on NuGet, which targets netstandard2.0 and netstandard2.1, runs faster simply by upgrading your application to .NET 9.0.
What message processing rate is achievable on modern laptop hardware? On a Surface Laptop Studio 2 with a 13th gen Intel Core i7-13800H, the library achieves 9.95 million messages per second for basic inspection and 8.73 million messages per second with a more realistic workload.
How has the cumulative performance changed since .NET Core 3.1? Performance has improved by well over double since .NET Core 3.1, thanks entirely to improvements in the .NET runtime, with no code changes required to the library.

Ian Griffiths

Technical Fellow I

Ian Griffiths

Ian has worked across an extraordinary breadth of computing - from embedded real-time systems and broadcast television to medical imaging and cloud-scale architectures. As Technical Fellow at endjin, he brings this deep cross-domain experience to bear on the hardest technical problems.

A 17-time Microsoft MVP in Developer Technologies, Ian is the author of O'Reilly's Programming C# 12.0 and one of the foremost authorities on the C# language and high-performance .NET development. He's a maintainer of Reactive Extensions for .NET, Reaqtor, and endjin's 50+ open source projects.

Ian has created Pluralsight courses on WPF fundamentals, WPF advanced topics, WPF v4, and the TPL, and has given over 20 talks at conferences worldwide. Technology brings him joy.