This document covers performance characteristics and benchmarking.
Running benchmarks:
go test -bench=. -benchmem ./...| Operation | Latency (P50) | Latency (P95) | Throughput |
|---|---|---|---|
| Insert | ~1μs | ~5μs | ~500K ops/sec |
| Get | ~0.5μs | ~2μs | ~1M ops/sec |
| Update | ~1.5μs | ~8μs | ~300K ops/sec |
| Delete | ~1μs | ~5μs | ~500K ops/sec |
| Query Type | Small (100) | Medium (10K) | Large (1M) |
|---|---|---|---|
| Primary key | ~0.5μs | ~1μs | ~5μs |
| Index lookup | ~1μs | ~10μs | ~100μs |
| Full scan | ~100μs | ~10ms | ~1s |
| Tx Size | Commit Time |
|---|---|
| 1 write | ~10μs |
| 10 writes | ~50μs |
| 100 writes | ~200μs |
| 1000 writes | ~2ms |
| Metric | Value |
|---|---|
| Upload throughput | ~10MB/s |
| Download throughput | ~15MB/s |
| Latency (per 100KB batch) | ~50ms |
| Merge overhead | ~10% |
Default: 4KB
Smaller pages:
- Better for small documents
- More page overhead
- Larger WAL
Larger pages:
- Better for large documents
- Less page overhead
- More internal fragmentation
Default: 1000 pages (~4MB)
Too small:
- High disk I/O
- Poor performance
Too large:
- Memory pressure
- OS swapping
Default: 16MB
Smaller:
- More frequent rotation
- More checkpointing
Larger:
- Longer recovery time
- More disk space during checkpoint
// BAD: Individual transactions
for _, item := range items {
tx, _ := db.Begin(true)
tx.Insert("items", toItem(item))
tx.Commit()
}
// GOOD: Single transaction
tx, _ := db.Begin(true)
for _, item := range items {
tx.Insert("items", toItem(item))
}
tx.Commit()schema.Fields["email"].Indexed = truequery.Limit = 100tx, _ := db.Begin(false) // Read-only
// ... reads ...
tx.Commit()Large documents (>100KB) should use blobs:
doc.Set("dataRef", blobStore.Put(largeData))go test -cpuprofile=cpu.prof -bench=. ./internal/storage
go tool pprof -http=:8080 cpu.profgo test -memprofile=mem.prof -bench=. ./internal/storage
go tool pprof -http=:8080 mem.profgo test -trace=trace.out ./internal/storage
go tool trace -http=:8080 trace.outStore benchmark baselines in testdata/benchmarks/:
# Save baseline
go test -bench=. ./... > testdata/benchmarks/baseline.txt
# Compare
benchstat testdata/benchmarks/baseline.txt <(go test -bench=. ./...)GitHub Actions runs benchmarks and fails if regression >10%:
- name: Run benchmarks
run: |
go test -bench=. -benchmem ./... > new.txt
benchstat testdata/benchmarks/baseline.txt new.txt- Large Transactions: Transactions with >10K writes may slow down commit
- Index Updates: Each index adds ~20% write overhead
- Encryption: Adds ~15% overhead to all operations
- Sync: Pauses database during sync (short duration)