High-performance UUID generator library implementing RFC 9562 with optional Rust FFI acceleration

dev-main / 1.x-dev 2025-07-04 02:31 UTC

This package is auto-updated.

Last update: 2025-07-04 02:37:01 UTC


README

A high-performance UUID generator library implementing RFC 9562 with support for UUIDv1-v8, featuring optional Rust FFI acceleration, async/sync compatibility, and high-concurrency collision prevention.

Features

  • Complete RFC 9562 Support: UUIDv1, v3, v4, v5, v6, v7, v8
  • High Performance: Optional Rust FFI acceleration
  • 🔄 Async/Sync Compatible: Works with both paradigms seamlessly
  • 🚀 Concurrency Support: RevoltPHP, AmphpV3, Parallel integration
  • 🛡️ Collision Prevention: Advanced mechanisms for high-throughput scenarios
  • 🔧 Configurable: Multiple RNG providers and performance options
  • 📦 Zero Dependencies: Pure PHP fallback when FFI unavailable
  • PHP 8.3+ Compatible: Supports PHP 8.3 and later versions

Installation

composer require highperapp/uuid

Optional: Rust FFI Acceleration

For maximum performance, you can enable Rust FFI acceleration which can improve UUID generation speed by up to 10x.

Prerequisites

  1. Install PHP FFI Extension (required for Rust acceleration):

    # Ubuntu/Debian
    sudo apt update
    sudo apt install php8.3-ffi php8.3-dev
    
    # CentOS/RHEL/Fedora
    sudo yum install php-ffi php-devel
    # or for newer versions:
    sudo dnf install php-ffi php-devel
    
    # macOS (with Homebrew)
    brew install php
    # FFI is usually included in modern PHP builds
    
    # Windows
    # Enable FFI in php.ini by uncommenting:
    # extension=ffi
  2. Verify FFI Installation:

    php -m | grep ffi
    # Should output: ffi
    
    # Test FFI functionality
    php -r "echo extension_loaded('ffi') ? 'FFI enabled' : 'FFI not available';"
  3. Install Rust (if not already installed):

    # Using rustup (recommended)
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    source $HOME/.cargo/env
    
    # Or using your system package manager
    # Ubuntu/Debian: sudo apt install rustc cargo
    # macOS: brew install rust
    # Windows: Download from https://rustup.rs/
  4. Verify Installation:

    rustc --version
    cargo --version

Build the Rust Library

cd rust
cargo build --release

The compiled library will be available at rust/target/release/libuuid_ffi.so (Linux/macOS) or rust/target/release/uuid_ffi.dll (Windows).

Troubleshooting FFI Issues

If you encounter FFI-related errors:

  1. FFI Not Available:

    # Check if FFI is installed
    php -m | grep ffi
    
    # Check PHP configuration
    php --ini | grep "Configuration File"
    
    # Enable FFI in php.ini
    echo "extension=ffi" | sudo tee -a /etc/php/8.3/cli/php.ini
  2. FFI Preloading Issues:

    # Set FFI preload in php.ini (optional for better performance)
    echo "ffi.preload=" | sudo tee -a /etc/php/8.3/cli/php.ini
  3. Permission Issues:

    # Ensure the compiled library has proper permissions
    chmod +x rust/target/release/libuuid_ffi.so
  4. Library Path Issues:

    // Test FFI with absolute path
    $ffi = FFI::cdef("", __DIR__ . "/rust/target/release/libuuid_ffi.so");

Development vs Production

  • Development: The library automatically falls back to pure PHP if Rust FFI is unavailable
  • Production: For optimal performance, ensure both FFI extension and Rust library are available
  • CI/CD: Add both FFI installation and Rust build steps to your deployment pipeline
  • Docker: Include FFI in your PHP Docker image and build Rust during image creation

Quick Start

use HighPerApp\HighPer\Uuid\Core\UuidFactory;

// Generate UUIDs
$uuid4 = UuidFactory::v4();  // Random UUID
$uuid7 = UuidFactory::v7();  // Timestamp-based UUID (recommended)
$uuid1 = UuidFactory::v1();  // Legacy timestamp + MAC

// Name-based UUIDs
$uuid3 = UuidFactory::v3(UuidFactory::NAMESPACE_DNS, 'example.com');
$uuid5 = UuidFactory::v5(UuidFactory::NAMESPACE_DNS, 'example.com');

// Convert and validate
$uuid = UuidFactory::fromString('550e8400-e29b-41d4-a716-446655440000');
$isValid = UuidFactory::isValid($uuid->toString());

echo $uuid->toString();   // 550e8400-e29b-41d4-a716-446655440000
echo $uuid->getVersion(); // 4

UUID Versions

UUIDv1 - Timestamp + MAC Address

$uuid = UuidFactory::v1();
echo $uuid->getTimestamp(); // Gregorian timestamp
echo $uuid->getNode();      // MAC address (or random)

UUIDv3 - MD5 Name-based

$uuid = UuidFactory::v3Dns('example.com');
// Always generates the same UUID for the same input

UUIDv4 - Random

$uuid = UuidFactory::v4();
// Cryptographically random

UUIDv5 - SHA-1 Name-based

$uuid = UuidFactory::v5Url('https://example.com');
// Always generates the same UUID for the same input

UUIDv6 - Reordered Timestamp

$uuid = UuidFactory::v6();
// Like v1 but with better database locality

UUIDv7 - Unix Timestamp (Recommended)

$uuid = UuidFactory::v7();
// Best for new applications - sortable and efficient

UUIDv8 - Custom Format

$uuid = UuidFactory::v8([
    'custom_fields' => [
        'timestamp' => time(),
        'counter' => 123
    ]
]);

Performance Configuration

High Performance Setup

use HighPerApp\HighPer\Uuid\Core\Configuration;
use HighPerApp\HighPer\Uuid\Core\UuidFactory;

$config = Configuration::highPerformance();
UuidFactory::configure($config);

// Now all UUID generation uses Rust FFI when available
$uuid = UuidFactory::v4(); // Uses Rust acceleration

Custom Configuration

$config = Configuration::default()
    ->setDefaultVersion(7)
    ->setRandomProvider('rust')
    ->enableFFI(true)
    ->setMaxConcurrentWorkers(8);

UuidFactory::configure($config);

Async/Concurrent Generation

Async Generation

use HighPerApp\HighPer\Uuid\Async\AsyncUuidFactory;

// Single async UUID
$uuid = AsyncUuidFactory::v4Async()->await();

// Batch generation
$uuids = AsyncUuidFactory::generateBatch(1000, 4)->await();

// Concurrent batch (using worker processes)
$uuids = AsyncUuidFactory::generateConcurrentBatch(10000, 4, 8)->await();

High-Throughput Scenarios

use HighPerApp\HighPer\Uuid\Async\ConcurrentGenerator;

$generator = new ConcurrentGenerator(8); // 8 worker processes
$uuids = $generator->generateConcurrent(100000, 4);
// Generates 100,000 UUIDs across 8 processes

Pipeline Processing

use HighPerApp\HighPer\Uuid\Async\AsyncUuidFactory;

$pipeline = AsyncUuidFactory::generatePipeline(10000, 7);

foreach ($pipeline as $uuid) {
    // Process each UUID as it's generated
    echo $uuid->toString() . "\n";
}

Random Number Providers

use HighPerApp\HighPer\Uuid\RandomProvider\RandomProviderFactory;

// Available providers
$providers = RandomProviderFactory::getAvailableProviders();
// ['secure', 'openssl', 'rust', 'pseudo']

// Create specific provider
$provider = RandomProviderFactory::create('rust');
$uuid = UuidFactory::v4($provider);

// Benchmark providers
$results = RandomProviderFactory::benchmark('rust', 1000);

Collision Prevention

The library includes advanced collision prevention mechanisms:

use HighPerApp\HighPer\Uuid\Concurrency\CollisionPrevention;

// Enable collision detection
$config = Configuration::default()
    ->enableCollisionPrevention(true);
UuidFactory::configure($config);

// The library automatically handles:
// - Timestamp collisions
// - High-frequency generation
// - Multi-process safety
// - Sequence management

Benchmarking

Run performance tests to validate performance on your system:

# Run built-in benchmarks (requires PHPBench)
vendor/bin/phpbench run benchmarks --report=default

# Quick performance test
php -r "
require 'vendor/autoload.php';
use HighPerApp\HighPer\Uuid\Core\UuidFactory;
\$start = microtime(true);
for (\$i = 0; \$i < 10000; \$i++) { UuidFactory::v4(); }
\$duration = microtime(true) - \$start;
echo 'Generated ' . number_format(10000 / \$duration) . ' UUIDs/second\n';
"

Expected Performance Ranges

  • Development environment: 300,000 - 600,000 UUIDs/second
  • Production environment: 600,000 - 900,000 UUIDs/second
  • With Rust FFI: 1,000,000+ UUIDs/second
  • High-concurrency scenarios: 400,000 - 800,000 UUIDs/second

Performance depends on:

  • CPU speed and architecture
  • PHP version and configuration
  • Available memory
  • FFI extension availability
  • Rust library compilation

Integration Examples

Laravel

// In a Laravel service provider
use HighPerApp\HighPer\Uuid\Core\Configuration;
use HighPerApp\HighPer\Uuid\Core\UuidFactory;

public function boot()
{
    UuidFactory::configure(Configuration::highPerformance());
}

// In your models
protected $keyType = 'string';
public $incrementing = false;

protected static function boot()
{
    parent::boot();
    
    static::creating(function ($model) {
        if (empty($model->id)) {
            $model->id = UuidFactory::v7()->toString();
        }
    });
}

Symfony

// services.yaml
services:
    HighPerApp\HighPer\Uuid\Core\Configuration:
        factory: ['HighPerApp\HighPer\Uuid\Core\Configuration', 'highPerformance']
    
    uuid_factory:
        class: HighPerApp\HighPer\Uuid\Core\UuidFactory
        calls:
            - configure: ['@HighPerApp\HighPer\Uuid\Core\Configuration']

Database Storage

-- MySQL
CREATE TABLE users (
    id BINARY(16) PRIMARY KEY,
    uuid_string CHAR(36) GENERATED ALWAYS AS (
        CONCAT(
            HEX(SUBSTR(id, 1, 4)), '-',
            HEX(SUBSTR(id, 5, 2)), '-',
            HEX(SUBSTR(id, 7, 2)), '-',
            HEX(SUBSTR(id, 9, 2)), '-',
            HEX(SUBSTR(id, 11, 6))
        )
    ) STORED,
    name VARCHAR(255)
);

-- PostgreSQL
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE users (
    id UUID PRIMARY KEY,
    name VARCHAR(255)
);

Performance Characteristics

Version Performance Use Case Sortable Collision Risk
v1 High Legacy systems No Very Low
v3 Medium Name-based, reproducible No None
v4 High General purpose No Negligible
v5 Medium Name-based, reproducible No None
v6 High Sortable timestamp Yes Very Low
v7 Highest Recommended for new apps Yes Very Low
v8 Variable Custom implementations Variable Variable

Throughput Benchmarks

Benchmarks measured on PHP 8.3.6, Linux x86_64. Performance may vary based on hardware and configuration.

Configuration UUIDs/second Memory/UUID Notes
Pure PHP v4 ~600,000-900,000 <100 bytes Actual performance exceeds estimates
Pure PHP v7 ~700,000-900,000 <100 bytes Recommended for new applications
Pure PHP v1 ~600,000 <100 bytes Legacy timestamp-based
Pure PHP v3/v5 ~850,000-900,000 <100 bytes Name-based UUIDs (cached)
Rust FFI v4 ~1,000,000+ <50 bytes Requires FFI extension + Rust build
Rust FFI v7 ~1,200,000+ <50 bytes Optimal for high-throughput scenarios
Concurrent v4 ~400,000-800,000 Variable Depends on worker count and overhead

Memory Usage Notes:

  • Memory per UUID is minimal in normal usage due to PHP's garbage collection
  • Bulk operations (10,000+ UUIDs) may use ~100-200 bytes per UUID temporarily
  • String representation adds ~36 bytes per UUID when stored
  • Memory usage scales linearly with batch size

Configuration Options

$config = new Configuration();

// Version settings
$config->setDefaultVersion(7);              // Default: 7

// Performance settings  
$config->enableFFI(true);                   // Default: true
$config->preferRustFFI(true);               // Default: true
$config->setMaxConcurrentWorkers(8);        // Default: 4

// Security settings
$config->setRandomProvider('secure');       // Default: 'secure'
$config->enableCollisionPrevention(true);   // Default: true

// Timestamp settings
$config->enableMonotonicTimestamp(true);    // Default: true
$config->setTimestampPrecision(1000);       // microseconds

// Namespaces
$config->addNamespace('custom', 'your-namespace-uuid');

Error Handling

use HighPerApp\HighPer\Uuid\Exception\GenerationException;
use HighPerApp\HighPer\Uuid\Exception\ValidationException;
use HighPerApp\HighPer\Uuid\Exception\ConfigurationException;

try {
    $uuid = UuidFactory::v3('invalid-namespace', 'name');
} catch (ValidationException $e) {
    // Handle validation errors
}

try {
    $uuid = UuidFactory::generate(99); // Invalid version
} catch (GenerationException $e) {
    // Handle generation errors
}

Development Setup

Prerequisites

  1. PHP 8.3+ with extensions:

    # Check required extensions
    php -m | grep -E "(ffi|openssl|json)"
    
    # Install missing extensions (Ubuntu/Debian)
    sudo apt install php8.3-ffi php8.3-openssl php8.3-json php8.3-dev
    
    # CentOS/RHEL/Fedora
    sudo yum install php-ffi php-openssl php-json php-devel
    
    # macOS (with Homebrew)
    brew install php
    
    # Verify FFI is working
    php -r "echo extension_loaded('ffi') ? 'FFI: ✓' : 'FFI: ✗';"
  2. Composer (for PHP dependencies):

    composer install
  3. Rust (optional, for FFI acceleration):

    # Install Rust if not already installed
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    source $HOME/.cargo/env
    
    # Build the Rust library
    cd rust && cargo build --release
    
    # Verify Rust FFI library is built
    ls -la rust/target/release/libuuid_ffi.so

Development Workflow

# 1. Install dependencies
composer install

# 2. (Optional) Build Rust FFI for performance
cd rust && cargo build --release && cd ..

# 3. Run tests
vendor/bin/phpunit

# 4. Run static analysis
vendor/bin/phpstan analyse

Testing

# Run tests
vendor/bin/phpunit

# Run with coverage
vendor/bin/phpunit --coverage-html coverage

# Run benchmarks
vendor/bin/phpbench run benchmarks --report=default

# Static analysis
vendor/bin/phpstan analyse

Requirements

  • PHP 8.3 or higher
  • ext-ffi (required for Rust FFI acceleration)
  • ext-openssl (required for secure random generation)
  • ext-json (required for configuration)
  • revolt/event-loop ^1.0
  • amphp/amp ^3.0
  • amphp/parallel ^2.0

FFI Configuration

For production environments, consider adding these settings to your php.ini:

# Enable FFI extension
extension=ffi

# Optional: Preload FFI for better performance
; ffi.preload=

# Optional: Set FFI scope (default is "preload")
; ffi.enable=preload

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

MIT License. See LICENSE for details.

Changelog

v1.0.0

  • Initial release
  • Complete RFC 9562 implementation
  • Rust FFI acceleration
  • Async/concurrent support
  • Comprehensive test suite