StableId 1.0.0
dotnet add package StableId --version 1.0.0
NuGet\Install-Package StableId -Version 1.0.0
<PackageReference Include="StableId" Version="1.0.0" />
<PackageVersion Include="StableId" Version="1.0.0" />
<PackageReference Include="StableId" />
paket add StableId --version 1.0.0
#r "nuget: StableId, 1.0.0"
#:package StableId@1.0.0
#addin nuget:?package=StableId&version=1.0.0
#tool nuget:?package=StableId&version=1.0.0
StableId
StableId is a high-performance deterministic GUID generator for .NET. Generate consistent, reproducible GUIDs from any input with exceptional performance characteristics.
Features
- โจ Deterministic: Same input always produces the same GUID
- ๐ High Performance: Optimized for speed with minimal allocations
- ๐ Thread Safe: Safe for concurrent use
- ๐ฆ Lightweight: Minimal dependencies
- ๐ฒ UUID v5 Compatible: Uses SHA-256 hashing for deterministic generation
- ๐ฏ Modern .NET: Built for .NET 9.0+
Quick Start
Installation
dotnet add package StableId
Basic Usage
using StableId;
// Generate GUID from string values
Guid id1 = DeterministicGuidGenerator.GenerateId("user@example.com");
Guid id2 = DeterministicGuidGenerator.GenerateId("user@example.com");
// id1 == id2 (always true)
// Generate from multiple values
Guid id3 = DeterministicGuidGenerator.GenerateId("Hello", "World", 123);
Guid id4 = DeterministicGuidGenerator.GenerateId("Hello", "World", 123);
// id3 == id4 (always true)
// Different input produces different GUID
Guid id5 = DeterministicGuidGenerator.GenerateId("Hello", "Universe");
// id5 != id3 (different input)
Smart Object Handling
The generator automatically extracts meaningful identifiers from objects using reflection:
using StableId;
// Objects with ID properties
var user = new { Id = Guid.NewGuid(), Name = "John Doe" };
var product = new { Key = 12345, ProductCode = "ABC123" };
var order = new { Identifier = 789L, Amount = 150.00m };
// Generate composite ID - uses ID properties, ignores other properties
Guid compositeId = DeterministicGuidGenerator.GenerateId(user, product, order);
// Same user with different name produces same ID (uses Id property)
var userDifferentName = new { Id = user.Id, Name = "Jane Smith" };
Guid sameId = DeterministicGuidGenerator.GenerateId(userDifferentName, product, order);
// compositeId == sameId โ
(uses Id property, ignores Name)
ID Property Priority Order:
IdGuidKeyIdentifierID
Advanced Usage
using StableId;
// High-frequency generation (optimized for performance)
for (int i = 0; i < 1_000_000; i++)
{
Guid id = DeterministicGuidGenerator.GenerateId("cache-key", i, DateTime.UtcNow.Ticks);
}
// Thread-safe concurrent usage
var tasks = Enumerable.Range(0, 1000)
.Select(i => Task.Run(() => DeterministicGuidGenerator.GenerateId($"input-{i}")))
.ToArray();
Guid[] results = await Task.WhenAll(tasks);
// Handle large inputs (automatic buffer management)
string largeString = new string('x', 10_000);
Guid largeId = DeterministicGuidGenerator.GenerateId(largeString);
// Complex objects with nested properties
var complexObject = new
{
Id = 12345,
User = new { Name = "John", Email = "john@example.com" },
Items = new[] { "item1", "item2", "item3" }
};
Guid complexId = DeterministicGuidGenerator.GenerateId(complexObject);
Performance Characteristics
- Ultra-High Throughput: 4.7M+ operations per second for simple inputs
- Sub-microsecond Latency: ~211ns average per operation
- Excellent Scalability: Linear scaling with thread count (65M+ ops/sec on 16 threads)
- Memory Efficient: Zero allocations for typical workloads
- Bounded Allocations: Uses
Span<T>,ArrayPool<T>, and stack allocation - Smart Buffering: Dynamic buffer sizing with overflow protection
Technical Details
UUID v5 Compliance
Generated GUIDs follow RFC 4122 UUID version 5 specification:
// Version bits (4 bits at position 48-51) set to 5
guidBytes[6] = (byte)((guidBytes[6] & 0x0F) | 0x50);
// Variant bits (2 bits at position 64-65) for RFC 4122 compliance
guidBytes[8] = (byte)((guidBytes[8] & 0x3F) | 0x80);
Security Features
- SHA-256 Hashing: Cryptographically secure hash function
- Collision Resistance: Null-byte separators prevent input collision attacks
- Type Safety: Input validation and bounds checking
- Recursion Protection: Maximum 10 levels of object nesting
Memory Management
- Stack Allocation: Uses
stackallocfor buffers โค 1KB - Array Pooling: Rents larger buffers from
ArrayPool<byte>.Shared - Span Operations: Zero-copy operations with
Span<T>andReadOnlySpan<T> - Cached Reflection: Property lookup results cached with bounded cache size (1000 entries)
Error Handling
The generator includes comprehensive error handling:
// Maximum parameter validation
DeterministicGuidGenerator.GenerateId(params); // Max 100 parameters
// Null parameter protection
DeterministicGuidGenerator.GenerateId("valid", null); // Throws ArgumentException
// Buffer overflow protection
string veryLargeString = new string('x', 100_000);
Guid id = DeterministicGuidGenerator.GenerateId(veryLargeString); // Handles gracefully
// Recursion protection
var deeplyNested = /* object with 20+ levels of nesting */;
Guid id = DeterministicGuidGenerator.GenerateId(deeplyNested); // Max 10 levels, then truncates
Use Cases
- ๐๏ธ Database Sharding: Consistent partition keys across services
- ๐พ Caching: Deterministic cache keys for distributed caches
- ๐ Distributed Systems: Reproducible identifiers across microservices
- ๐ Data Processing: Deduplication and entity matching
- ๐๏ธ Event Sourcing: Stable aggregate identifiers
- ๐งช Testing: Predictable test data generation
- ๐ ETL Pipelines: Consistent record matching across data sources
Thread Safety
DeterministicGuidGenerator is fully thread-safe:
- Static methods with no mutable state
- Thread-safe caching with
ConcurrentDictionary<T,K> - Atomic cache size tracking with
Interlockedoperations - No shared mutable state between operations
Requirements
- .NET 9.0+ (uses latest performance features)
- C# 12+ (modern language features)
Project Structure
StableId/
โโโ src/
โ โโโ StableId/
โ โโโ DeterministicGuidGenerator.cs # Main implementation
โ โโโ StableId.csproj # Project file
โโโ examples/
โ โโโ StableId.Examples/ # Usage examples
โโโ tests/
โ โโโ StableId.Tests/ # Unit tests
โโโ benchmarks/
โ โโโ StableId.Benchmarks/ # Performance benchmarks
โโโ README.md
Building and Testing
# Clone the repository
git clone https://github.com/henrikroschmann/StableId.git
cd StableId
# Build the solution
dotnet build
# Run tests
dotnet test
# Run examples
dotnet run --project examples/StableId.Examples
# Run benchmarks
dotnet run --project benchmarks/StableId.Benchmarks -c Release
# Or use the convenience scripts:
# Windows: run-benchmarks.bat [core|comparison|concurrency|memory]
# PowerShell: ./run-benchmarks.ps1 [core|comparison|concurrency|memory]
Performance Benchmarks
Core Performance Results
| Scenario | Mean Time | Allocation | Throughput |
|---|---|---|---|
| Single Short String | 211 ns | 0 B | ~4.7M ops/sec |
| Multiple Parameters | 287 ns | 0 B | ~3.5M ops/sec |
| Complex Objects | 728 ns | 4 KB | ~1.4M ops/sec |
| Very Long Strings | 4.1 ฮผs | 65 KB | ~240K ops/sec |
Comparison with Alternatives
| Method | Mean Time | Memory | Ratio vs StableId |
|---|---|---|---|
| StableId.GenerateId | 211 ns | 32 B | 1.00x |
| Guid.NewGuid() | 40 ns | 0 B | 0.19x (non-deterministic) |
| Manual SHA256 | 437 ns | 328 B | 2.08x |
| String.GetHashCode() | 6 ns | 0 B | 0.03x (not cryptographic) |
Concurrency Performance
| Thread Count | Operations/sec | Scalability |
|---|---|---|
| 1 Thread | 4.7M ops/sec | 100% |
| 4 Threads | 18.2M ops/sec | 387% |
| 8 Threads | 34.8M ops/sec | 741% |
| 16 Threads | 65.1M ops/sec | 1,385% |
Memory Efficiency
- Zero allocations for simple scenarios
- Minimal allocations for complex inputs
- Stack allocation preferred for buffers โค 1KB
- Array pooling for larger temporary buffers
- Bounded memory usage even with very large inputs
Test Environment: .NET 9.0, Arm64 (Snapdragon X), Release build
Examples
See the examples/StableId.Examples project for comprehensive usage examples including:
- Basic string-based ID generation
- Smart object handling with ID property extraction
- Performance demonstrations
- Thread safety examples
- Complex object scenarios
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Add tests for new functionality
- Ensure all tests pass (
dotnet test) - Follow existing code style and patterns
- Submit a pull request
License
MIT License - see LICENSE file for details.
Acknowledgments
- Inspired by RFC 4122 UUID specification (Version 5 - Name-based UUIDs)
- Built with .NET performance best practices
- Uses modern memory management techniques (
Span<T>,ArrayPool<T>,stackalloc)
โญ Star this repo if StableId helps you build more efficient applications!
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 976 | 10/28/2025 |