Skip to content

Commit

Permalink
Merge pull request #15 from romadanskiy/benchmarks
Browse files Browse the repository at this point in the history
Benchmark across .NET versions
  • Loading branch information
aevitas authored Feb 28, 2024
2 parents d934436 + 1a02d88 commit 77be4e1
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 57 deletions.
49 changes: 35 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,49 @@ Alternatively, there is a `ToStringIdentifier()` extension method available whic

## Performance

We've benchmarked FlakeId on .NET 5 against [MassTransit's NewId](https://github.com/phatboyg/NewId) library, and [IdGen](https://github.com/RobThree/IdGen) both libraries are widely used. It is worth noting that NewId generates 128-bit integers.
We've benchmarked FlakeId on .NET 8 against [MassTransit's NewId](https://github.com/phatboyg/NewId) library, and [IdGen](https://github.com/RobThree/IdGen) both libraries are widely used. It is worth noting that NewId generates 128-bit integers.

We've also included `Guid.NewGuid` as a baseline benchmark, as it is very well optimized, and arguably the most widely used identifier generator in .NET.

```
BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042
Intel Core i7-8700K CPU 3.70GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET Core SDK=5.0.201
[Host] : .NET Core 5.0.4 (CoreCLR 5.0.421.11614, CoreFX 5.0.421.11614), X64 RyuJIT
DefaultJob : .NET Core 5.0.4 (CoreCLR 5.0.421.11614, CoreFX 5.0.421.11614), X64 RyuJIT
| Method | Mean | Error | StdDev | Code Size |
|--------------- |------------:|-----------:|-----------:|----------:|
| Single_FlakeId | 30.44 ns | 0.091 ns | 0.080 ns | 254 B |
| Single_Guid | 59.47 ns | 0.681 ns | 0.637 ns | 111 B |
| Single_NewId | 75.27 ns | 0.323 ns | 0.270 ns | 40 B |
| Single_IdGen | 2,445.98 ns | 176.372 ns | 520.036 ns | 687 B |
BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3155/23H2/2023Update/SunValley3)
AMD Ryzen 5 5600X, 1 CPU, 12 logical and 6 physical cores
.NET SDK 8.0.201
[Host] : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
| Method | Mean | Error | StdDev | Code Size |
|--------------- |------------:|----------:|-----------:|----------:|
| Single_FlakeId | 26.48 ns | 0.020 ns | 0.019 ns | 358 B |
| Single_Guid | 41.85 ns | 0.481 ns | 0.450 ns | 245 B |
| Single_NewId | 31.83 ns | 0.013 ns | 0.012 ns | 303 B |
| Single_IdGen | 3,473.96 ns | 69.295 ns | 168.673 ns | 671 B |
```

In this benchmark, IdGen was configured to `SpinWait` in the event multiple IDs were generated in the same instant. It spent most of its time in a spinlock.

Below are the benchmark results for FlakeId running on multiple runtimes.

```
BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3155/23H2/2023Update/SunValley3)
AMD Ryzen 5 5600X, 1 CPU, 12 logical and 6 physical cores
.NET SDK 8.0.201
[Host] : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
.NET 5.0 : .NET 5.0.17 (5.0.1722.21314), X64 RyuJIT AVX2
.NET 6.0 : .NET 6.0.27 (6.0.2724.6912), X64 RyuJIT AVX2
.NET 7.0 : .NET 7.0.16 (7.0.1624.6629), X64 RyuJIT AVX2
.NET 8.0 : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
| Method | Job | Runtime | Mean | Error | StdDev | Code Size |
|--------------- |--------- |--------- |---------:|---------:|---------:|----------:|
| Single_FlakeId | .NET 5.0 | .NET 5.0 | 27.85 ns | 0.111 ns | 0.103 ns | 254 B |
| Single_FlakeId | .NET 6.0 | .NET 6.0 | 26.37 ns | 0.056 ns | 0.053 ns | 215 B |
| Single_FlakeId | .NET 7.0 | .NET 7.0 | 26.72 ns | 0.211 ns | 0.176 ns | 209 B |
| Single_FlakeId | .NET 8.0 | .NET 8.0 | 26.56 ns | 0.085 ns | 0.071 ns | 358 B |
```

## Issues

If you have an issue with FlakeId, please open an issue and describe your problem as accurately as you can.
Expand Down
10 changes: 5 additions & 5 deletions src/FlakeId.Benchmarks/FlakeId.Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>net8.0;net7.0;net6.0;net5.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.12.1" />
<PackageReference Include="IdGen" Version="3.0.0" />
<PackageReference Include="NewId" Version="3.0.3" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.12" />
<PackageReference Include="IdGen" Version="3.0.3" />
<PackageReference Include="NewId" Version="4.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
21 changes: 21 additions & 0 deletions src/FlakeId.Benchmarks/FlakeIdMultipleRuntimesBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnostics.Windows.Configs;
using BenchmarkDotNet.Jobs;

namespace FlakeId.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net50)]
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net70)]
[SimpleJob(RuntimeMoniker.Net80)]
[DisassemblyDiagnoser]
[InliningDiagnoser(true, null)]
public class FlakeIdMultipleRuntimesBenchmarks
{
[Benchmark]
public void Single_FlakeId()
{
Id.Create();
}
}
}
40 changes: 40 additions & 0 deletions src/FlakeId.Benchmarks/IdCreationBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnostics.Windows.Configs;
using IdGen;
using MassTransit;

namespace FlakeId.Benchmarks
{
[DisassemblyDiagnoser]
[InliningDiagnoser(true, null)]
public class IdCreationBenchmarks
{
private static readonly IdGenerator s_idGenerator = new IdGenerator(10,
new IdGeneratorOptions(sequenceOverflowStrategy: SequenceOverflowStrategy.SpinWait));

[Benchmark]
public void Single_FlakeId()
{
Id.Create();
}

[Benchmark]
public void Single_Guid()
{
Guid.NewGuid();
}

[Benchmark]
public void Single_NewId()
{
NewId.Next();
}

[Benchmark]
public void Single_IdGen()
{
s_idGenerator.CreateId();
}
}
}
40 changes: 2 additions & 38 deletions src/FlakeId.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnostics.Windows.Configs;
using BenchmarkDotNet.Running;
using IdGen;
using MassTransit;
using BenchmarkDotNet.Running;

namespace FlakeId.Benchmarks
{
Expand All @@ -12,38 +7,7 @@ internal class Program
private static void Main(string[] args)
{
BenchmarkRunner.Run<IdCreationBenchmarks>();
}
}

[DisassemblyDiagnoser]
[InliningDiagnoser(true, null)]
public class IdCreationBenchmarks
{
private static readonly IdGenerator s_idGenerator = new IdGenerator(10,
new IdGeneratorOptions(sequenceOverflowStrategy: SequenceOverflowStrategy.SpinWait));

[Benchmark]
public void Single_FlakeId()
{
Id.Create();
}

[Benchmark]
public void Single_Guid()
{
Guid.NewGuid();
}

[Benchmark]
public void Single_NewId()
{
NewId.Next();
}

[Benchmark]
public void Single_IdGen()
{
s_idGenerator.CreateId();
BenchmarkRunner.Run<FlakeIdMultipleRuntimesBenchmarks>();
}
}
}

0 comments on commit 77be4e1

Please sign in to comment.