Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Single-Threaded Power 🚀

Demonstrating that single-threaded, lock-free architectures can outperform traditional multi-threaded approaches

A comprehensive C# demonstration project showcasing various concurrency patterns and their performance characteristics, from traditional database locking to high-performance lock-free architectures inspired by the LMAX Disruptor pattern.

📋 Table of Contents

🎯 Overview

This project demonstrates the evolution from traditional locking mechanisms to high-performance single-threaded processing using a ticket reservation system as the domain model. Each demo progressively removes layers of locking and overhead, culminating in a mechanical sympathy-focused architecture that achieves 10x-50x performance improvements.

The Journey

  1. Demo 1: SQL Database Locking (100-500 TPS) - Traditional ACID with pessimistic/optimistic locking
  2. Demo 2: In-Memory Locks (1,000-3,000 TPS) - Remove database overhead, expose lock contention
  3. Demo 3: Single-Threaded (10,000-50,000+ TPS) - Lock-free ring buffer with mechanical sympathy

📁 Project Structure

single-threaded-power/
├── src/
│   ├── single-threaded-power.sln             # Solution file
│   ├── SingleThreadedPower.Domain/           # Shared domain models & interfaces
│   ├── SingleThreadedPower.Demo1.SqlLocking/ # Database locking demo
│   ├── SingleThreadedPower.Demo2.InMemoryLocks/ # In-memory locking patterns
│   ├── SingleThreadedPower.Demo3.SingleThreaded/ # Lock-free Disruptor pattern
│   ├── SingleThreadedPower.LoadGenerator/    # Performance testing framework
│   ├── SingleThreadedPower.Console/          # Interactive demo runner
│   └── SingleThreadedPower.Tests/            # Unit & benchmark tests
└── docs/                                     # Additional documentation

🎪 Demos

Demo 1: SQL Locking

Demonstrates traditional database concurrency control with Entity Framework Core 8.

Features:

  • ✅ Pessimistic Locking (SELECT FOR UPDATE with UPDLOCK, ROWLOCK hints)
  • ✅ Optimistic Locking (version/timestamp-based)
  • ✅ Deadlock scenarios and handling
  • ✅ Connection pooling configuration
  • ✅ Lock wait time logging with interceptors
  • ✅ Testcontainers for isolated MS SQL Server instances

Expected Performance: 100-500 TPS

Demo 2: In-Memory Locks

Eliminates database overhead to demonstrate that locks are still a bottleneck.

Implementations:

  • LockBasedReservationService: Traditional lock statements with global, per-event, and per-seat strategies
  • SemaphoreReservationService: SemaphoreSlim for throttling with fairness problem demonstrations
  • ReaderWriterReservationService: ReaderWriterLockSlim for read-heavy workloads
  • CSharp13LockReservationService: Using new System.Threading.Lock (C# 13/.NET 9)

Metrics:

  • Lock contention tracking
  • Context switching overhead
  • CPU utilization analysis

Expected Performance: 1,000-3,000 TPS

Demo 3: Single-Threaded Lock-Free

High-performance single-threaded processing with mechanical sympathy.

Architecture:

  • DisruptorReservationService: Lock-free ring buffer with single consumer thread
  • RingBuffer: Pre-allocated, power-of-2 sized, cache-line padded array
  • ReservationCommand: Value-type command pattern (readonly record struct)
  • TaskCompletionSource: Async responses without blocking

Modern C# Features:

  • ref struct for zero-allocation
  • Span<T> and Memory<T> for efficient memory access
  • ValueTask<T> for reduced allocations
  • [SkipLocalsInit] for performance
  • Static abstract interface members

Expected Performance: 10,000-50,000+ TPS with p99 latency < 1ms

🛠️ Prerequisites

🚀 Getting Started

Clone the Repository

git clone https://github.com/joeldickson/single-threaded-power.git
cd single-threaded-power

Build the Solution

# Build the solution
cd src
dotnet build single-threaded-power.sln -c Release

# Or build specific demo
dotnet build SingleThreadedPower.Demo3.SingleThreaded/SingleThreadedPower.Demo3.SingleThreaded.csproj -c Release

Run the Interactive Console

cd src/SingleThreadedPower.Console
dotnet run

The console provides an interactive menu to:

  • Select which demo to run
  • Configure event size, concurrent users, and test duration
  • View real-time metrics with live updating dashboards
  • Compare different approaches side-by-side

Run Tests

cd src
dotnet test SingleThreadedPower.Tests/SingleThreadedPower.Tests.csproj

💡 Key Concepts

Mechanical Sympathy

Understanding and working with the hardware (CPU cache lines, memory alignment, false sharing) rather than against it.

Techniques Used:

  • Cache-line padding to prevent false sharing
  • Power-of-2 sizing for efficient modulo operations
  • Sequential memory access patterns
  • Minimizing allocations in hot paths

Lock-Free Programming

Using atomic operations and memory barriers instead of traditional locks.

Benefits:

  • No context switching overhead
  • Predictable latency
  • Better CPU cache utilization
  • Scalability without lock contention

The Disruptor Pattern

A high-performance inter-thread messaging library pattern created by LMAX Exchange.

Core Ideas:

  • Pre-allocated ring buffer
  • Single writer principle
  • Batching for efficiency
  • Minimizing write contention

📊 Performance Targets

Demo Throughput (TPS) Avg Latency P99 Latency CPU Efficiency
SQL Locking 100-500 10-50ms 100-500ms Low (I/O bound)
In-Memory Locks 1,000-3,000 1-5ms 10-50ms Medium (contention)
Single-Threaded 10,000-50,000+ <0.5ms <1ms High (cache-friendly)

🔧 Technologies Used

  • C# 12 / .NET 8: Primary language features (collection expressions, primary constructors)
  • Entity Framework Core 8: Database access and locking demos
  • Testcontainers: Disposable test infrastructure
  • Spectre.Console: Beautiful terminal UI
  • xUnit / BenchmarkDotNet: Testing and performance measurement

📚 Further Reading

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

📝 License

This project is licensed under the MIT License - see the LICENSE file for details.

👤 Author

Joel Dickson

⭐ Show Your Support

Give a ⭐️ if this project helped you understand high-performance concurrency patterns!


Built with ❤️ to demonstrate that sometimes the best way to handle concurrency is to avoid it altogether.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages