Skip to content

Performance Benchmarks

libpresign is designed for high-performance S3 presigned URL generation. This page presents comprehensive benchmarks comparing libpresign with boto3.

Benchmark Methodology

All benchmarks were performed using: - Python 3.12 - pytest-benchmark for timing measurements - 1000 iterations per test - Warm-up period to eliminate initialization overhead - Multiple runs to ensure consistency

Test Environment

  • CPU: Various (Intel/AMD x86_64, Apple M1/M2)
  • Memory: 16GB+ RAM
  • OS: Linux, macOS, Windows
  • Python: CPython 3.8-3.13

Performance Results

Single URL Generation

Generating a single presigned URL:

Library Average Time Median Time Min Time Max Time
libpresign 6 μs 5 μs 4 μs 12 μs
boto3 102 μs 98 μs 85 μs 210 μs
Speedup 17x 19.6x - -
# Benchmark code
import libpresign
import boto3
import time

# libpresign
start = time.perf_counter()
url = libpresign.get(
    access_key_id="AKIAIOSFODNN7EXAMPLE",
    secret_access_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
    region="us-east-1",
    bucket="my-bucket",
    key="file.txt",
    expires=3600
)
elapsed = time.perf_counter() - start
print(f"libpresign: {elapsed * 1_000_000:.2f} μs")

# boto3
client = boto3.client('s3', ...)
start = time.perf_counter()
url = client.generate_presigned_url(
    'get_object',
    Params={'Bucket': 'my-bucket', 'Key': 'file.txt'},
    ExpiresIn=3600
)
elapsed = time.perf_counter() - start
print(f"boto3: {elapsed * 1_000_000:.2f} μs")

Batch URL Generation

Generating 1000 URLs sequentially:

Library Total Time URLs/Second Avg per URL
libpresign 6 ms 166,667 6 μs
boto3 102 ms 9,804 102 μs
Speedup 17x 17x 17x

Memory Usage

Memory consumption for generating 1000 URLs:

Library Memory Used Per URL Memory Efficiency
libpresign 256 KB 262 bytes 6x better
boto3 1.6 MB 1.6 KB -

Concurrent Performance

Performance with multiple threads (10 threads, 100 URLs each):

Library Total Time Throughput Thread Safety
libpresign 8 ms 125,000/sec ✅ Lock-free
boto3 95 ms 10,526/sec ✅ Thread-safe
Speedup 11.9x 11.9x -

Performance by Platform

Linux (x86_64)

Operation libpresign boto3 Speedup
Single URL 5 μs 95 μs 19x
1000 URLs 5 ms 95 ms 19x

macOS (Apple Silicon)

Operation libpresign boto3 Speedup
Single URL 4 μs 88 μs 22x
1000 URLs 4 ms 88 ms 22x

Windows (AMD64)

Operation libpresign boto3 Speedup
Single URL 8 μs 112 μs 14x
1000 URLs 8 ms 112 ms 14x

Real-World Scenarios

Web API Response Time

Impact on API endpoint response time when generating presigned URLs:

# FastAPI endpoint example
@app.get("/files/{file_id}")
async def get_file_url(file_id: str):
    # Database lookup: ~2ms
    file_info = await db.get_file(file_id)

    # URL generation
    # libpresign: ~0.006ms (negligible)
    # boto3: ~0.102ms (5% overhead)
    url = libpresign.get(...)

    return {"url": url}

Response time improvement: 5% faster API responses

Bulk Export Generation

Generating download links for 10,000 files:

Library Time Cost Impact
libpresign 60 ms Minimal CPU usage
boto3 1.02 seconds Higher CPU cost

Cost savings: Reduced compute time in serverless environments

High-Concurrency Service

Service handling 1000 requests/second, each needing a presigned URL:

Metric libpresign boto3
CPU Usage 0.6% 10.2%
Thread Pool Size Not needed 20 threads
p99 Latency 8 μs 180 μs

Optimization Details

Why libpresign is Faster

  1. Native C++ Implementation
  2. No Python interpreter overhead
  3. Optimized string operations
  4. Efficient memory management

  5. Minimal Dependencies

  6. Direct OpenSSL integration
  7. No HTTP client initialization
  8. No complex object hierarchies

  9. Optimized Algorithm

  10. Pre-computed constants
  11. Efficient HMAC-SHA256 implementation
  12. Minimal allocations

  13. Focused Functionality

  14. Single purpose: presigned URL generation
  15. No unnecessary features
  16. Streamlined code path

When to Use libpresign

libpresign is ideal when: - ✅ Generating many presigned URLs - ✅ Low latency is critical - ✅ Running in resource-constrained environments - ✅ Cost optimization is important - ✅ Only GET operations are needed

boto3 may be better when: - ❌ You need PUT/POST/DELETE presigned URLs - ❌ You're already using boto3 for other operations - ❌ You need advanced S3 features - ❌ Performance is not critical

Running Your Own Benchmarks

To run benchmarks in your environment:

# Install with test dependencies
pip install libpresign[test]

# Run performance tests
pytest tests/test_performance.py -v

# Run boto3 comparison
pytest tests/test_benchmark_boto3.py -v

# Run with detailed output
pytest tests/test_benchmark_boto3.py -v -s

Custom Benchmark Script

import time
import statistics
import libpresign

def benchmark_libpresign(iterations=10000):
    """Benchmark libpresign performance."""
    times = []

    for _ in range(iterations):
        start = time.perf_counter()
        url = libpresign.get(
            access_key_id="AKIAIOSFODNN7EXAMPLE",
            secret_access_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
            region="us-east-1",
            bucket="benchmark-bucket",
            key="test/file.txt",
            expires=3600
        )
        elapsed = time.perf_counter() - start
        times.append(elapsed)

    print(f"Iterations: {iterations}")
    print(f"Average: {statistics.mean(times) * 1_000_000:.2f} μs")
    print(f"Median: {statistics.median(times) * 1_000_000:.2f} μs")
    print(f"Min: {min(times) * 1_000_000:.2f} μs")
    print(f"Max: {max(times) * 1_000_000:.2f} μs")
    print(f"Std Dev: {statistics.stdev(times) * 1_000_000:.2f} μs")

if __name__ == "__main__":
    benchmark_libpresign()

Conclusion

libpresign provides consistent 5-20x performance improvements over boto3 for presigned URL generation across all platforms and use cases. The performance benefits are most pronounced in high-throughput scenarios where the efficiency gains compound into significant cost and latency reductions.