|
20 | 20 | <p align="center"> |
21 | 21 | <img src="https://img.shields.io/badge/Swift-6.2-orange.svg" alt="Swift 6.2"> |
22 | 22 | <img src="https://img.shields.io/badge/platforms-iOS%2026%20%7C%20macOS%2026-blue.svg" alt="Platforms"> |
23 | | - <img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"> |
| 23 | + <img src="https://img.shields.io/badge/license-Apache_2.0-green.svg" alt="License"> |
24 | 24 | </p> |
25 | 25 |
|
26 | 26 | --- |
@@ -104,16 +104,120 @@ Cold Open → First Query: 17ms |
104 | 104 | Hybrid Search @ 10K docs: 105ms |
105 | 105 | ``` |
106 | 106 |
|
| 107 | +### Core Benchmark Baselines (as of February 17, 2026) |
| 108 | + |
| 109 | +These are reproducible XCTest benchmark baselines captured from the current Wax benchmark harness. |
| 110 | + |
| 111 | +#### Ingest throughput (`testIngestHybridBatchedPerformance`) |
| 112 | + |
| 113 | +| Workload | Time | Throughput | |
| 114 | +|:---|---:|---:| |
| 115 | +| smoke (200 docs) | `0.103s` | `~1941.7 docs/s` | |
| 116 | +| standard (1000 docs) | `0.309s` | `~3236.2 docs/s` | |
| 117 | +| stress (5000 docs) | `2.864s` | `~1745.8 docs/s` | |
| 118 | +| 10k | `7.756s` | `~1289.3 docs/s` | |
| 119 | + |
| 120 | +#### Search latency |
| 121 | + |
| 122 | +| Workload | Time | Throughput | |
| 123 | +|:---|---:|---:| |
| 124 | +| warm CPU smoke | `0.0015s` | `~666.7 ops/s` | |
| 125 | +| warm CPU standard | `0.0033s` | `~303.0 ops/s` | |
| 126 | +| warm CPU stress | `0.0072s` | `~138.9 ops/s` | |
| 127 | +| 10k CPU hybrid iteration | `0.103s` | `~9.7 ops/s` | |
| 128 | + |
| 129 | +#### Recall latency (`testMemoryOrchestratorRecallPerformance`) |
| 130 | + |
| 131 | +| Workload | Time | |
| 132 | +|:---|---:| |
| 133 | +| smoke | `0.103s` | |
| 134 | +| standard | `0.101s` | |
| 135 | + |
| 136 | +Stress recall is currently harness-blocked (`signal 11`) and treated as a known benchmark issue. |
| 137 | + |
| 138 | +#### FastRAG builder |
| 139 | + |
| 140 | +| Mode | Time | |
| 141 | +|:---|---:| |
| 142 | +| fast mode | `0.102s` | |
| 143 | +| dense cached | `0.102s` | |
| 144 | + |
| 145 | +For benchmark commands, profiling traces, and methodology, see: |
| 146 | +- `/Users/chriskarani/CodingProjects/Wax/Tasks/hot-path-specialization-investigation.md` |
| 147 | + |
107 | 148 | *No, that's not a typo. GPU vector search really is sub-millisecond.* |
108 | 149 |
|
109 | 150 | --- |
110 | 151 |
|
| 152 | +## WAL Compaction and Storage Health (2026-02) |
| 153 | + |
| 154 | +Wax now includes a WAL/storage health track focused on commit latency tails, long-run file growth, and recovery behavior: |
| 155 | + |
| 156 | +- No-op index compaction guards to avoid unnecessary index rewrites. |
| 157 | +- Single-pass WAL replay with guarded replay snapshot fast path. |
| 158 | +- Proactive WAL-pressure commits for targeted workloads (guarded rollout). |
| 159 | +- Scheduled `rewriteLiveSet` maintenance with dead-payload thresholds, validation, and rollback. |
| 160 | + |
| 161 | +### Measured outcomes |
| 162 | + |
| 163 | +- Repeated unchanged index compaction growth improved from `+61,768,464` bytes over 8 runs (`~7.72MB/run`) to bounded drift (test-gated). |
| 164 | +- Commit latency improved in most matrix workloads in recent runs (examples: `medium_hybrid` p95 `-13.9%`, `large_text_10k` p95 `-8.0%`, `sustained_write_text` p95 `-5.7%`). |
| 165 | +- Reopen/recovery p95 is generally flat-to-improved across the matrix. |
| 166 | +- `sustained_write_hybrid` remains workload-sensitive, so proactive/scheduled maintenance stays guarded by default. |
| 167 | + |
| 168 | +### Safe rollout defaults |
| 169 | + |
| 170 | +- Proactive pressure commits are tuned for targeted workloads and validated with percentile guardrails. |
| 171 | +- Replay snapshot open-path optimization is additive and guarded. |
| 172 | +- Scheduled live-set rewrite is configurable and runs deferred from the `flush()` hot path. |
| 173 | +- Rewrite candidates are automatically validated and rolled back on verification failure. |
| 174 | + |
| 175 | +### Configure scheduled live-set rewrite |
| 176 | + |
| 177 | +```swift |
| 178 | +import Wax |
| 179 | + |
| 180 | +var config = OrchestratorConfig.default |
| 181 | +config.liveSetRewriteSchedule = LiveSetRewriteSchedule( |
| 182 | + enabled: true, |
| 183 | + checkEveryFlushes: 32, |
| 184 | + minDeadPayloadBytes: 64 * 1024 * 1024, |
| 185 | + minDeadPayloadFraction: 0.25, |
| 186 | + minimumCompactionGainBytes: 0, |
| 187 | + minimumIdleMs: 15_000, |
| 188 | + minIntervalMs: 5 * 60_000, |
| 189 | + verifyDeep: false |
| 190 | +) |
| 191 | +``` |
| 192 | + |
| 193 | +### Reproduce benchmark matrix |
| 194 | + |
| 195 | +```bash |
| 196 | +WAX_BENCHMARK_WAL_COMPACTION=1 \ |
| 197 | +WAX_BENCHMARK_WAL_OUTPUT=/tmp/wal-matrix.json \ |
| 198 | +swift test --filter WALCompactionBenchmarks.testWALCompactionWorkloadMatrix |
| 199 | +``` |
| 200 | + |
| 201 | +```bash |
| 202 | +WAX_BENCHMARK_WAL_GUARDRAILS=1 \ |
| 203 | +swift test --filter WALCompactionBenchmarks.testProactivePressureCommitGuardrails |
| 204 | +``` |
| 205 | + |
| 206 | +```bash |
| 207 | +WAX_BENCHMARK_WAL_REOPEN_GUARDRAILS=1 \ |
| 208 | +swift test --filter WALCompactionBenchmarks.testReplayStateSnapshotGuardrails |
| 209 | +``` |
| 210 | + |
| 211 | +See `/Users/chriskarani/CodingProjects/Wax/Tasks/wal-compaction-investigation.md` and `/Users/chriskarani/CodingProjects/Wax/Tasks/wal-compaction-baseline.json` for methodology and full baseline artifacts. |
| 212 | + |
| 213 | +--- |
| 214 | + |
111 | 215 | ## Quick Start |
112 | 216 |
|
113 | 217 | ### 1. Add to Package.swift |
114 | 218 |
|
115 | 219 | ```swift |
116 | | -.package(url: "https://github.com/christopherkarani/Wax.git", from: "0.1.1") |
| 220 | +.package(url: "https://github.com/christopherkarani/Wax.git", from: "0.1.6") |
117 | 221 | ``` |
118 | 222 |
|
119 | 223 | ### 2. Choose Your Memory Type |
|
0 commit comments