# Deep dive into .NET 11 Performance Improvements #4

In this series, I explore some of the most interesting .NET 11 performance improvements described in Stephen Toub's blog post, [Performance Improvements in .NET 11](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-11).

Each post focuses on one example from the original article while digging a little deeper into an additional aspect that was not covered there. The series covers the following topics:

1. [Allocation free numbers](https://blog.ladeak.net/posts/net11-perf-imp-01.md)
1. [Virtual generic method calls](https://blog.ladeak.net/posts/net11-perf-imp-02.md)
1. [Vector zero equality](https://blog.ladeak.net/posts/net11-perf-imp-03.md)
1. *Current post: [Guid creation on Linux](https://blog.ladeak.net/posts/net11-perf-imp-04.md)*
1. JIT generating implicit-else assembly instructions
1. Guid equality
1. Copy-on-write locking strategy

## Guid creation on Linux

In .NET 11, the `Guid.NewGuid()` method received performance improvements through its random number generation. The original post notes that random number generation on Linux has been somewhat slower than on Windows. The original post however shows no performance benchmarks.

My questions:

- What is the measured impact of this change from .NET 10 to .NET 11?
- How does .NET 11 compare on Windows and Linux today?
- How does this all compare to the `CreateVersion7()` method?

Let's answer these using the following benchmark:

```csharp
public class Benchmarks
{
    [Benchmark]
    public void CreateNew() => Guid.NewGuid();
    [Benchmark]
    public void CreateNewV7() => Guid.CreateVersion7();
}
```

While the original post does not include concrete performance measurements, the impact is substantial: on my machine, running Ubuntu 26.04 in WSL, `Guid.NewGuid()` is about 7x faster in .NET 11:

Runtime=.NET 10.0

```
| Method      | Mean     | Error   | StdDev  |
|------------ |---------:|--------:|--------:|
| CreateNew   | 286.0 ns | 3.12 ns | 2.76 ns |
| CreateNewV7 | 306.3 ns | 1.73 ns | 1.53 ns |
```

Runtime=.NET 11.0

```
| Method      | Mean     | Error    | StdDev   |
|------------ |---------:|---------:|---------:|
| CreateNew   | 40.65 ns | 0.519 ns | 0.486 ns |
| CreateNewV7 | 59.39 ns | 0.873 ns | 0.816 ns |
```

When I run the same tests on the same machine under Windows, the measurements indicate that Linux and Windows performance are on par:

```
Runtime=.NET 11.0
| Method      | Mean     | Error    | StdDev   |
|------------ |---------:|---------:|---------:|
| CreateNew   | 40.71 ns | 0.756 ns | 0.707 ns |
| CreateNewV7 | 59.50 ns | 0.249 ns | 0.220 ns |
```

These measurements also show that creating a UUID version 7, a millisecond ordered unique identifier, is somewhat slower. On Linux with .NET 10, the difference was relatively small: `CreateNewV7` was about 7% slower than `CreateNew`. In .NET 11, it was about 46% slower.

## Conclusion

This post focused on the fourth of seven nuances I learned from the [Performance Improvements in .NET 11](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-11) article. It examined the performance improvements for [Guid](https://learn.microsoft.com/en-us/dotnet/api/system.guid), compared Linux and Windows performance, and compared the creation of non time ordered and time ordered GUIDs.