- CPU: AMD Ryzen 9 9950X 16-Core Processor
- OS: Windows
- Go Version: (latest)
- Date: 2025-07-21
Basic implementation with no optimizations.
| Operation | Time/op | Bytes/op | Allocs/op |
|---|---|---|---|
| Simple log | 150.5 ns | 288 B | 8 |
| Below minimum level | 1.4 ns | 0 B | 0 |
| With 2 properties | 412.4 ns | 1040 B | 21 |
| With 5 properties | 858.6 ns | 2384 B | 39 |
| With context | 231.6 ns | 576 B | 9 |
Added template caching and property map pooling.
| Operation | Time/op | Bytes/op | Allocs/op | Improvement |
|---|---|---|---|---|
| Simple log | 100.2 ns | 128 B | 2 | 33% faster |
| Below minimum level | 1.4 ns | 0 B | 0 | - |
| With 2 properties | 82.5 ns | 32 B | 1 | 80% faster |
| With 5 properties | 154.8 ns | 80 B | 1 | 82% faster |
| With context | 87.7 ns | 0 B | 0 | 62% faster |
Implemented SimpleSink interface for zero-allocation simple logging.
| Operation | Time/op | Bytes/op | Allocs/op | Improvement |
|---|---|---|---|---|
| Simple log | 13.6 ns | 0 B | 0 | 91% faster |
| Below minimum level | 1.4 ns | 0 B | 0 | - |
| With 2 properties | 182.9 ns | 448 B | 4 | 56% faster |
| With 5 properties | 248.4 ns | 496 B | 4 | 71% faster |
| With context | 197.1 ns | 416 B | 3 | 15% faster |
-
Template Caching
- Templates are parsed once and cached
- Eliminates repeated parsing overhead
- Thread-safe with RWMutex
-
Property Map Pooling
- Reuses map allocations via sync.Pool
- Reduces GC pressure
- Maps cleared and returned to pool
-
Zero-Allocation Fast Path
- SimpleSink interface for direct string output
- Bypasses LogEvent creation for simple messages
- Conditions: no args, no properties, no enrichers, no filters
-
Eliminated Double Parsing
- ExtractPropertyNames works with already-parsed templates
- Removed redundant parsing in property extraction
-
Source Context Caching
- Caches source context by program counter
- Eliminates repeated runtime stack walking
- Thread-safe with RWMutex
- Significant performance improvement for source context enrichment
| Logger | Simple Log | Allocations | Notes |
|---|---|---|---|
| mtlog | 13.6 ns | 0 | With fast path |
| mtlog | 100.2 ns | 2 | Without fast path |
| zap | ~50 ns | 0 | Requires complex API |
| zerolog | ~50 ns | 0 | Different API style |
| logrus | ~3000 ns | 20+ | Feature-rich but slow |
| stdlib log | ~200 ns | 2+ | Basic functionality |
# Run all benchmarks
go test -bench=. -benchmem -run=^$
# Run specific benchmarks
go test -bench=BenchmarkSimpleLog -benchmem -run=^$
# Run with longer duration for stability
go test -bench=. -benchmem -run=^$ -benchtime=10s
# Compare allocations
go test -run=TestAllocationBreakdown -v-
String Interning
- Cache common log messages
- Reduce string allocations
-
SIMD Operations
- Use SIMD for bulk property copying
- Optimize timestamp formatting
-
Lock-Free Sinks
- Implement lock-free ring buffers
- Reduce contention in high-throughput scenarios
-
Compile-Time Optimization
- Generate specialized code for common patterns
- Use code generation for type-specific paths
To analyze memory usage:
go test -bench=BenchmarkSimpleLog -memprofile=mem.prof
go tool pprof mem.profTo analyze CPU usage:
go test -bench=BenchmarkSimpleLog -cpuprofile=cpu.prof
go tool pprof cpu.profWhen adding new features:
- Always run benchmarks before and after changes
- Use
testing.AllocsPerRunto verify allocation counts - Consider the fast path - will this feature disable it?
- Add feature-specific benchmarks
- Document any performance trade-offs
- Simple logging: < 20ns/op, 0 allocations ✓
- Structured logging: < 200ns/op, < 5 allocations ✓
- Below minimum level: < 2ns/op, 0 allocations ✓
- Memory usage: Minimal heap pressure
- Concurrency: Scale linearly with cores