|
| 1 | +# bdcache Benchmarks |
| 2 | + |
| 3 | +This directory contains comparison benchmarks against popular Go cache libraries. |
| 4 | + |
| 5 | +## ⚠️ Important Disclaimers |
| 6 | + |
| 7 | +### Cherrypicked Benchmarks |
| 8 | + |
| 9 | +These benchmarks are **intentionally cherrypicked** to demonstrate S3-FIFO's strengths: |
| 10 | + |
| 11 | +- **Scan resistance workloads** - Where large scans of cold data shouldn't evict hot working set |
| 12 | +- **One-hit wonder scenarios** - Where many items are accessed once and shouldn't pollute the cache |
| 13 | +- **Memory-only Get operations** - Pure speed comparisons without I/O |
| 14 | + |
| 15 | +**Different workloads favor different algorithms:** |
| 16 | +- **LRU** excels with temporal locality and simple sequential access patterns |
| 17 | +- **TinyLFU (Ristretto)** shines with frequency-based workloads and large caches |
| 18 | +- **S3-FIFO** handles mixed workloads with both hot items and one-hit wonders |
| 19 | + |
| 20 | +Your mileage **will** vary based on: |
| 21 | +- Access patterns (sequential, random, zipfian, etc.) |
| 22 | +- Working set size vs cache capacity |
| 23 | +- Read/write ratio |
| 24 | +- Key/value sizes |
| 25 | +- Hardware (CPU, memory speed) |
| 26 | + |
| 27 | +### The Real Differentiator: Persistence |
| 28 | + |
| 29 | +**bdcache's primary advantage isn't raw speed or hit rates** - it's the automatic per-item persistence designed for unreliable cloud environments: |
| 30 | + |
| 31 | +- **Cloud Run** - Instances shut down unpredictably after idle periods |
| 32 | +- **Kubernetes** - Pods can be evicted, rescheduled, or killed anytime |
| 33 | +- **Container environments** - Restarts lose all in-memory data |
| 34 | +- **Crash recovery** - Application failures don't lose cache state |
| 35 | + |
| 36 | +Other libraries require manual save/load of the entire cache, which: |
| 37 | +- Doesn't work when shutdowns are unexpected |
| 38 | +- Requires coordination and timing logic |
| 39 | +- Risks data loss on crashes |
| 40 | +- Adds operational complexity |
| 41 | + |
| 42 | +## Running Benchmarks |
| 43 | + |
| 44 | +### Speed Comparison |
| 45 | + |
| 46 | +```bash |
| 47 | +go test -bench=BenchmarkSpeed -benchmem |
| 48 | +``` |
| 49 | + |
| 50 | +Compares raw Get operation performance across: |
| 51 | +- bdcache (S3-FIFO) |
| 52 | +- golang-lru (LRU) |
| 53 | +- otter (S3-FIFO with manual persistence) |
| 54 | +- ristretto (TinyLFU) |
| 55 | + |
| 56 | +### Hit Rate Comparison |
| 57 | + |
| 58 | +```bash |
| 59 | +go test -run=TestFIFOvsLRU_ScanResistance -v |
| 60 | +``` |
| 61 | + |
| 62 | +Demonstrates S3-FIFO's scan resistance with a cherrypicked workload: |
| 63 | +1. Build 8K item working set (fits in 10K cache) |
| 64 | +2. Access working set once (marks as hot) |
| 65 | +3. One-time scan through 10K cold items |
| 66 | +4. Re-access working set (should hit) |
| 67 | + |
| 68 | +**Results:** |
| 69 | +- S3-FIFO: 100% hit rate (working set protected in Main queue) |
| 70 | +- LRU: 0% hit rate (scan evicted entire working set) |
| 71 | + |
| 72 | +This is a **best-case scenario for S3-FIFO**. Many real workloads won't see this dramatic of a difference. |
| 73 | + |
| 74 | +### Additional Tests |
| 75 | + |
| 76 | +```bash |
| 77 | +# S3-FIFO correctness tests |
| 78 | +go test -run=TestS3FIFO -v |
| 79 | + |
| 80 | +# Detailed behavior demonstrations |
| 81 | +go test -run=TestS3FIFODetailed -v |
| 82 | + |
| 83 | +# Hit rate comparisons (mixed workloads) |
| 84 | +go test -run=TestHitRateComparison -v |
| 85 | +``` |
| 86 | + |
| 87 | +## Benchmark Files |
| 88 | + |
| 89 | +- `benchmark_comparison_test.go` - Speed benchmarks across libraries |
| 90 | +- `hitrate_comparison_test.go` - Hit rate workload generators |
| 91 | +- `fifo_vs_lru_test.go` - S3-FIFO vs LRU scan resistance demo |
| 92 | +- `s3fifo_debug_test.go` - Queue behavior validation |
| 93 | +- `s3fifo_detailed_test.go` - Detailed eviction order verification |
| 94 | + |
| 95 | +## Interpreting Results |
| 96 | + |
| 97 | +When evaluating caches for your use case: |
| 98 | + |
| 99 | +1. **Profile your actual workload** - Synthetic benchmarks don't capture real-world complexity |
| 100 | +2. **Measure what matters** - Hit rate, latency, throughput, memory usage |
| 101 | +3. **Consider operational needs** - Persistence, observability, graceful degradation |
| 102 | +4. **Test with your data** - Key/value sizes and access patterns vary wildly |
| 103 | +5. **Benchmark in production-like environments** - Hardware and load matter |
| 104 | + |
| 105 | +**Don't choose a cache based solely on these benchmarks.** Choose based on your specific requirements, with special attention to operational characteristics like persistence if you're running in unreliable cloud environments. |
0 commit comments