Skip to content

joeldickson/single-threaded-power

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

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

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages