A high-performance, thread-safe, no_std asynchronous logging library for Rust utilizing a lock-free Single-Producer Single-Consumer (SPSC) / Multi-Producer Single-Consumer (MPSC) architecture.
This library is designed for low-latency systems and embedded applications where runtime string parsing and global kernel synchronization overhead must be avoided.
- Execution Speed: Up to 100 times faster than the standard
logfacade in microbenchmarks usingstd::hint::black_box. - Zero Allocations: Operates entirely without heap allocations (
no_std). Memory for buffers is statically allocated at compile time. - Lock-free Pipeline: Worker threads push structured log events into a ring buffer using atomic operations, bypassing immediate physical I/O (UART, SSD, Network).
- Compile-time Configuration: The total number of ring buffer slots (
NB) and the maximum message array length (NL) are fixed at compile time via generics.
Tested with 100,000 logging operations in release mode (--release):
=== BENCHMARK ===
BREVNO: 203.239µs
LOG: 14.89848ms
BREVNO IS 73 TIMES FASTER!
=================
Instead of dynamic dispatch (&dyn Display) and sequential string parsing at runtime, BREVNO uses a lightweight adapter implementation around core::fmt::write.
The LLVM optimizer inlines and unrolls the formatting logic into flat byte copying operations directly into the memory region allocated for the target thread's slot, mitigating thread contention on the hot path.
Generate the global logger instance with chosen generic constraints at the root of your application using the initialization macro:
// Configuration: (Buffer capacity, Maximum message length in bytes, Default LogLevel)
crate::init_global_logger!(1024, 64, LogLevel::Info);Invoke the logging macros from any context. The macros reference the configured static instance, evaluate the active filter level, and write bytes atomically:
use crate::info;
fn main() {
info!("System initialized successfully");
std::thread::spawn(|| {
let user_id = 42;
// Supports standard formatting traits via core::fmt
info!("User {} established connection", user_id);
});
}While worker threads enqueue logs asynchronously, a background consumer task processes individual entries from the buffer and writes them to the final output destination:
// Within a background processing loop
while let Some(log) = GLOBAL_LOGGER.read_log() {
if let Ok(text) = log.decode() {
println!("{}", text); // Outputs: [INFO] System initialized...
}
}- Atomic Filtering: Log levels are checked using
AtomicU8operations withOrdering::Relaxedsequencing, enabling minimal processing overhead for disabled levels. - Static Resolution: The structure eliminates dynamic allocations during execution by ensuring that buffer sizes are strictly bounded via generic constraints.
Licensed under the MIT License.