High-Performance Deadlock and Race Condition Detection Engine
Production-ready concurrent safety monitoring with < 5% overhead
δΈζζζ‘£ | Usage Guide | Performance Report
Writing concurrent programs in Rust/C++/Go is challenging. The two most dreaded issues:
- Deadlocks: Program freezes after running for days
- Data Races: Data corruption without any visible symptoms
ThreadSanitizer (TSan):
- β Detects issues
- β 10-50x performance overhead
- β 5-10x memory overhead
- β Cannot deploy to production
The Gap: No tool exists for real-time production monitoring of concurrent safety issues.
β
< 5% performance overhead - Production-ready
β
Real-time detection - Immediate alerts
β
Precise localization - File, line, thread
β
Zero-intrusion - Just replace Mutex type
β
Comprehensive - Both deadlock and race detection
[dependencies]
thread-sentry = "0.1"use thread_sentry::{Mutex, init, report_issues};
fn main() {
init();
let data = Arc::new(Mutex::new(0u64));
// Just replace std::sync::Mutex β thread_sentry::Mutex
thread::spawn(|| {
let mut guard = data.lock();
*guard = 100; // Auto-detect + Auto-print
});
report_issues();
}use thread_sentry::{Mutex, SentryField, init};
struct SharedData {
counter: SentryField<u64>, // Auto-track field access
}
fn main() {
init();
let data = Arc::new(Mutex::new(SharedData::new()));
thread::spawn(|| {
let mut guard = data.lock();
guard.counter.set(100); // Auto-detect + Auto-print
});
report_issues();
}use thread_sentry::{RaceDetector, AccessType};
unsafe {
*raw_ptr = value;
// Manual registration for unsafe code
RaceDetector::record_access_manual(
addr, thread_id, AccessType::Write, lock_id, size
);
}See USAGE_GUIDE.md for detailed examples.
| Tool | Performance Overhead | Memory Overhead | Production Ready |
|---|---|---|---|
| TSan | 500-5000% | 5-10x | β No |
| Helgrind | 2000-3000% | 3-5x | β No |
| Thread-Sentry | < 5% | < 2x | β Yes |
| Metric | std::sync | parking_lot | Thread-Sentry |
|---|---|---|---|
| Latency | 50ns | 38ns (-24%) | 48ns (-4%) |
| Throughput | 20M ops/sec | 26M ops/sec (+30%) | 21M ops/sec (+5%) |
Key Finding: Thread-Sentry has only 4% overhead vs std::sync::Mutex.
See Performance Report for detailed benchmarks.
Automatically detects circular lock dependencies:
let lock1 = Mutex::new(0);
let lock2 = Mutex::new(0);
// Thread 1: lock1 -> lock2
// Thread 2: lock2 -> lock1
// Thread-Sentry detects the cycle and reports immediately!Output:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β οΈ DEADLOCK DETECTED β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Cycle Length: 2 locks
Lock Chain:
[1] Lock #1 held by Thread 1
Backtrace:
1. main.rs:15 - transfer_money()
[2] Lock #2 held by Thread 2
Backtrace:
1. main.rs:22 - process_transaction()
Detects unsynchronized concurrent memory access:
// Thread 1: write without lock
x = 100; // Write, no lock
// Thread 2: read without lock
read x; // Read, no lock
// Thread-Sentry detects the race condition!Output:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β‘ RACE CONDITION DETECTED β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Memory Address: 0x7f8a3c001000
Access 1: Write at bank.rs:30 (Thread 1, no lock)
Access 2: Read at bank.rs:45 (Thread 2, no lock)
Thread-Sentry is built on three layers:
βββββββββββββββββββββββββββββββββββββββββββ
β Application Layer β
β SentinelMutex / SentinelRwLock β β Replace standard locks
βββββββββββββββββββββββββββββββββββββββββββ€
β Monitoring Layer β
β - Lock event tracking β β Intercept lock/unlock
β - Thread state management β
β - Dependency graph construction β
βββββββββββββββββββββββββββββββββββββββββββ€
β Detection Layer β β Real-time analysis
β - Deadlock detector (cycle detection) β
β - Race detector (access tracking) β
βββββββββββββββββββββββββββββββββββββββββββ
See Architecture Documentation for details.
- Usage Guide - Three detection methods explained
- Architecture - Technical implementation details
- Performance Report - Performance test results
- Project Summary - Complete project overview
- δΈζζζ‘£ - Chinese documentation
// Development: Enable full monitoring
#[cfg(debug_assertions)]
use thread_sentry::Mutex;
// Production: Selective monitoring
#[cfg(not(debug_assertions))]
{
thread_sentry::init();
// Use Thread-Sentry for critical locks only
// Use parking_lot for high-frequency paths
}// Initialize with custom settings
thread_sentry::init();
// Use different lock types
let critical_lock = Mutex::new(data); // Full monitoring
let fast_lock = RwLock::new(cache); // Read-write monitoringcargo test# Demo
cargo run --example demo
# Benchmark
cargo run --example benchmark
# Real-world scenario
cargo run --example real_world# See docs/PERFORMANCE_TESTING_GUIDE.md for details
scripts\run_benchmarks.batAdvantages:
- β < 1% overhead (very low)
- β Basic deadlock detection
Limitations:
- β No race condition detection
- β 10-second polling delay
- β Limited information (only lock IDs)
- β Not suitable for CI/CD
Advantages:
- β Real-time detection (0 delay)
- β Race condition detection
- β Precise localization (file, line, thread)
- β Suitable for development and CI/CD
- β Production-ready (< 5% overhead)
Trade-off:
- Higher overhead (6% vs < 1%)
Use both:
- Development: Thread-Sentry (comprehensive diagnosis)
- Production: parking_lot (long-term monitoring)
- Critical paths: Thread-Sentry (safety priority)
- High-frequency: parking_lot (performance priority)
β High-concurrency services
- Web servers, API endpoints
- Database connection pools
- Message queue systems
β Long-running applications
- Background services
- Scheduled tasks
- Event-driven systems
β Critical business logic
- Financial transactions
- Inventory management
- Order processing
β Development and debugging
- Real-time feedback
- CI/CD integration
- Early problem detection
- Single-threaded applications
- Extremely performance-sensitive scenarios (< 5% overhead unacceptable)
- Already using other detection tools
use thread_sentry::Mutex;
use std::sync::Arc;
struct BankAccount {
id: u64,
balance: f64,
}
fn transfer(from: Arc<Mutex<BankAccount>>, to: Arc<Mutex<BankAccount>>, amount: f64) {
let from_account = from.lock();
let to_account = to.lock(); // Thread-Sentry checks for deadlock
from_account.balance -= amount;
to_account.balance += amount;
}use thread_sentry::Mutex;
let buffer = Arc::new(Mutex::new(Vec::new()));
// Producer
thread::spawn(|| {
let mut buf = buffer.lock();
buf.push(item);
});
// Consumer
thread::spawn(|| {
let mut buf = buffer.lock();
if let Some(item) = buf.pop() {
process(item);
}
});- DashMap: Lock-free concurrent hash map
- SmallVec: Stack-allocated small arrays
- Incremental detection: Only check new edges
- Lazy backtrace: Collect only when issues found
Deadlock:
- Build dependency graph
- DFS cycle detection
- Real-time graph updates
Race Condition:
- Track memory access history
- Happens-before analysis
- Conflict detection
- Async lock support (tokio::sync::Mutex)
- Statistical sampling (< 1% overhead)
- Visualization tools (dependency graph SVG)
- Structured logging output
- Distributed deadlock detection (cross-service)
- ML-based problem prediction
- GPU-accelerated graph analysis
- IDE plugin integration
Contributions are welcome! Please feel free to submit issues and pull requests.
git clone https://github.com/yourusername/thread-sentry.git
cd thread-sentry
cargo build
cargo testMIT License
Built with amazing Rust community libraries:
- parking_lot: High-performance lock implementation
- dashmap: Concurrent hash map
- crossbeam: Concurrent primitives
- backtrace: Stack trace collection
Thread-Sentry: Making concurrent programming safer, one lock at a time. π‘οΈ