Hybrid SPSC Logger: Proof-of-Concept
📌 Overview
This project is a cross-platform, modern C++17 proof-of-concept demonstrating how to implement a high-performance, thread-friendly logging queue using hybrid SPSC (Single Producer Single Consumer) queues. It is designed to be a drop-in backend concept that could eventually integrate with loggers such as g3log, but this demo intentionally avoids any dependency on existing frameworks.
🧠 Key Concepts
Why Hybrid SPSC?
Traditional MPSC (Multi-Producer Single Consumer) lock-free queues offer good average performance, but exhibit unpredictable latency spikes under contention.
SPSC queues, on the other hand, are highly efficient and predictable due to no contention—but only work between one producer and one consumer.
This proof-of-concept creates one SPSC queue per producer thread, dynamically established and managed with thread_local.
The consumer thread round-robins through all active SPSC queues, efficiently aggregating logs with minimal latency and high predictability.
Key Benefits
Amortized performance: Each thread operates with no locking after initialization.
Predictability: No spikes from contention, unlike MPSC.
Automatic cleanup: Threads call setConnection() and tearDownConnection() to manage queue lifetimes.
Scalable: Can handle many producers efficiently.
⚖️ Comparison with Other Queue Models
🔄 vs. MPMC Lock-Free Queue (e.g., spdlog)
Pros of Hybrid SPSC:
Much more predictable latency profile (no high tail spikes).
Easier to reason about thread-to-queue relationships.
Minimal false sharing/cache invalidation due to SPSC isolation.
Cons Compared to MPMC:
Requires dynamic setup of per-thread queues.
Consumer has to actively poll multiple queues (vs. single dequeue).
Can become inefficient if many queues are mostly idle.
🔐 vs. MPMC Mutex-Protected Queue (e.g., g3log)
Pros of Hybrid SPSC:
Avoids locks entirely in steady-state after setup.
Scales far better with core count, especially under pressure.
Predictable even under high concurrency.
Cons Compared to Mutex-Based:
Slightly more complex to implement and debug.
Setup/teardown cost per thread, though amortized well.
Mutex-based queues can be simpler for small-scale applications with few producers.
⚙️ How It Works
Components
main.cpp — the core implementation and driver
spsc_circular_fifo.hpp — a lightweight, lock-free, fixed-size SPSC queue
Flow
Producer thread first calls log() → this calls setConnection() if needed
A new SPSC queue is created and added to the shared consumer pool
Subsequent log() calls go directly into the thread’s queue (no locking)
The consumer thread loops over all queues and pops available messages
When the thread completes its task, it calls tearDownConnection() to unregister its queue
Example Console Output
[INFO] Set up new thread-local queue connection on thread 140735301760768 Log: Thread 0 says hello 0 ... [INFO] Tear down called from thread 140735301760768 at time 56301230801290 [INFO] Removing queue from consumer on thread 123145302810624
🧪 How to Build and Run
macOS / Linux
g++ -std=c++17 -O2 -pthread main.cpp -o hybrid_logger ./hybrid_logger
Windows (Developer Command Prompt)
cl /std:c++17 /O2 /EHsc main.cpp main.exe
🔌 Potential Integration: g3log / spdlog / custom sinks
You could easily adapt this model to hook into existing logging libraries:
g3log: Replace the current lock-based queue in the LogWorker backend with a hybrid SPSC queue dispatcher
spdlog: Use the SPSC structure as a log sink that receives messages per-thread and dispatches them to the formatting/backend thread
Custom: Use it to send metrics, diagnostics, or messages to a real-time system without incurring blocking or contention
🧱 What Next?
Add a prioritized polling strategy to favor hot queues
Collect metrics (queue depth, drop rate, latency)
Expand for dynamic runtime scaling with thread-safe registry
This model offers a fresh, lightweight concurrency pattern suitable for high-performance logging, message dispatching, or real-time monitoring systems. The hybrid SPSC pattern can be the secret weapon for predictable, scalable thread communication in C++.
Hybrid SPSC Logging Model Evaluation
Summary of Discussion: Hybrid SPSC Queue-Based Logging
Overview:
Viability:
Accuracy:
Performance vs spdlog:
Technical Merits:
Limitations:
Recommendations:
Conclusion:
This hybrid SPSC model is promising for systems needing predictable low-latency logging. With
added instrumentation, dynamic cleanup, and benchmarking, it could outperform traditional logging
queues in real-world high-performance systems.
Code Examples
Example: RAII-style Logging Setup