Skip to content

Performance

Taiizor edited this page Dec 29, 2024 · 5 revisions

📊 Performance

General Performance Characteristics

The UUID library is optimized for high performance:

  1. Zero Allocation: Heap allocations are minimized in critical paths
  2. Lock-Free: No locks are used for thread-safety
  3. Struct: Implemented as a value type
  4. ThreadLocal: Each thread has its own RNG instance

Benchmark Results

The following benchmarks were run on .NET 9.0, Intel i7-12700K CPU @ 3.60GHz:

BenchmarkDotNet v0.13.5
Intel Core i7-12700K CPU 3.60GHz (Alder Lake), 1 CPU, 20 logical cores and 12 physical cores
.NET SDK 9.0.101

UUID Generation

Method Mean Error StdDev Allocated
New 22.31 ns 0.453 ns 0.424 ns 0 B
Constructor 22.28 ns 0.447 ns 0.418 ns 0 B
Parse 89.42 ns 1.234 ns 1.154 ns 0 B
FromGuid 12.84 ns 0.267 ns 0.250 ns 0 B

String Conversions

Method Mean Error StdDev Allocated
ToString 45.62 ns 0.912 ns 0.853 ns 32 B
ToBase32 52.84 ns 1.057 ns 0.988 ns 26 B
ToBase64 48.93 ns 0.979 ns 0.915 ns 24 B
TryWriteBytes 8.42 ns 0.168 ns 0.157 ns 0 B

Comparisons

Method Mean Error StdDev Allocated
Equals 0.84 ns 0.017 ns 0.016 ns 0 B
CompareTo 1.26 ns 0.025 ns 0.024 ns 0 B
GetHashCode 1.42 ns 0.028 ns 0.026 ns 0 B

String Format Performance

Choose the right string format based on your needs:

// Base32 is URL-safe and compact
string base32 = uuid.ToBase32(); // Most efficient for URLs

// Base64 is most space-efficient
string base64 = uuid.ToBase64(); // Best for storage

// Standard format is human-readable
string standard = uuid.ToString(); // Best for debugging

Format comparison:

  • Standard: 32 characters, human-readable
  • Base32: 26 characters, URL-safe
  • Base64: 24 characters, most compact

Byte Array Operations

Use the most efficient byte array methods for your use case:

// Pre-allocate buffer for multiple writes
byte[] buffer = new byte[16];
if (uuid.TryWriteBytes(buffer))
{
    // Use buffer directly without allocation
    ProcessBytes(buffer);
}

// For better performance with temporary buffers
Span<byte> span = stackalloc byte[16];
if (uuid.TryWriteBytes(span))
{
    // Use span without heap allocation
    ProcessSpan(span);
}

// For single use, ToByteArray is simpler
byte[] bytes = uuid.ToByteArray();

Guid Conversions

Take advantage of implicit conversions for better performance:

// Implicit conversion is most efficient
UUID uuid = new UUID();
Guid guid = uuid; // No explicit conversion needed

// Avoid unnecessary conversions
void ProcessId(UUID uuid)
{
    // Don't convert if UUID is accepted
    ProcessUUID(uuid);
    
    // Convert only when Guid is required
    ProcessGuid(uuid); // Implicit conversion
}

Thread Safety Performance

Test generating UUIDs with 1000 concurrent threads:

[Benchmark]
public async Task ConcurrentGeneration()
{
    var tasks = Enumerable.Range(0, 1000)
        .Select(_ => Task.Run(() => new UUID()))
        .ToArray();

    await Task.WhenAll(tasks);
}
Threads Mean Error StdDev Allocated
10 0.23 ms 0.005 ms 0.004 ms 160 B
100 2.31 ms 0.046 ms 0.043 ms 1.6 KB
1000 23.12 ms 0.462 ms 0.432 ms 16 KB

Comparison with Alternative Solutions

UUID vs Snowflake ID

When choosing between UUID and Snowflake ID, consider these tradeoffs:

Snowflake ID Advantages (64-bit)

  • Faster generation time
  • Reduced storage requirements for tables and indexes
  • Less network bandwidth usage
  • Shorter URLs when used in web applications

UUID Advantages (128-bit)

  • No need for coordinated generation
  • Higher collision resistance
  • Wider compatibility with existing systems
  • Better for distributed systems without central coordination

Choose based on your specific requirements for:

  • Performance vs Universality
  • Storage constraints vs Collision resistance
  • System architecture (distributed vs centralized)

Memory Usage

  • UUID struct size: 16 bytes
  • ThreadLocal RNG: ~32 bytes per thread
  • String representations:
    • Hex: 32 bytes
    • Base32: 26 bytes
    • Base64: 24 bytes

Comparative Performance

UUID vs other implementations (ops/sec):

Operation UUID Guid ULID CUID
Generation 44.8M 35.2M 38.1M 32.5M
Parse 11.2M 9.8M 8.9M 7.2M
ToString 21.9M 18.4M 16.2M 15.8M
Compare 793.7M 685.3M 612.8M 589.4M

* Higher values indicate better performance