diff --git a/api/v1-audit.txt b/api/v1-audit.txt index 57a6a53..4bc94ee 100644 --- a/api/v1-audit.txt +++ b/api/v1-audit.txt @@ -288,9 +288,9 @@ field VersionedOptions.RefreshDebounce time.Duration ok versioned.go:58 additive field VersionedStatus.CompletedBuilds uint64 ok versioned.go:73 additive R2/R3 contract; source-span and limit parity verified in scan_test.go:1, cache and coalescing in versioned_reuse_test.go:1 field VersionedStatus.DownloadedBuckets int ok versioned.go:73 additive R2/R3 contract; source-span and limit parity verified in scan_test.go:1, cache and coalescing in versioned_reuse_test.go:1 field VersionedStatus.ReusedBuckets int ok versioned.go:73 additive R2/R3 contract; source-span and limit parity verified in scan_test.go:1, cache and coalescing in versioned_reuse_test.go:1 -field VersionedOptions.DeltaSearch bool ok versioned.go:60 opt-in small-update search; publication and compaction verified in versioned_overlay_test.go:1 -field VersionedStatus.DeltaKeywords int ok versioned.go:80 overlay keyword count verified in versioned_overlay_test.go:1 -field VersionedStatus.DeltaSearch bool ok versioned.go:80 overlay state verified in versioned_overlay_test.go:1 +field VersionedOptions.DeltaSearch bool ok versioned.go:60 retained for source compatibility; single-engine behavior verified in versioned_test.go:119 +field VersionedStatus.DeltaKeywords int ok versioned.go:80 retained for source compatibility; zero value verified in versioned_test.go:141 +field VersionedStatus.DeltaSearch bool ok versioned.go:80 retained for source compatibility; disabled state verified in versioned_test.go:141 method (*AhoCorasick) MaskText(ctx context.Context, text string, mask rune, opts *RewriteOptions) (*RewriteResult, error) ok rewrite.go:41 additive R2/R3 contract; source-span and limit parity verified in scan_test.go:1, cache and coalescing in versioned_reuse_test.go:1 method (*AhoCorasick) ReplaceText(ctx context.Context, text, replacement string, opts *RewriteOptions) (*RewriteResult, error) ok rewrite.go:35 additive R2/R3 contract; source-span and limit parity verified in scan_test.go:1, cache and coalescing in versioned_reuse_test.go:1 method (*AhoCorasick) Scan(ctx context.Context, text string, opts *ScanOptions) (*ScanResult, error) ok scan.go:70 additive R2/R3 contract; source-span and limit parity verified in scan_test.go:1, cache and coalescing in versioned_reuse_test.go:1 diff --git a/benchmarks/results/v3-20260915-redis.json b/benchmarks/results/v3-20260915-redis.json new file mode 100644 index 0000000..c0aa289 --- /dev/null +++ b/benchmarks/results/v3-20260915-redis.json @@ -0,0 +1,7374 @@ +{ + "date": "2026-09-15", + "commit": "212179f26ae22454b65afae0d8d761f375d897c5", + "backend": "redis", + "endpoint": "127.0.0.1:6379", + "host": "Apple M4, 10 logical CPUs, macOS Darwin 25.6.0, arm64", + "go": "1.26.7", + "redis": "8.10.1", + "configuration": "Standalone localhost TCP, current server configuration, MemoryEfficient preset, 50ms polling, default 5 minute leases; three runs per size/distribution, separate Go process per run; seed 20260906.", + "caveats": [ + "Developer workstation, not an isolated performance lab; no latency or memory guarantee.", + "Redis memory and network counters are server-wide and include protocol, polling, engine downloads, script cache, and retained generations.", + "Prune advances generation timestamps past the retention horizon; it does not wait 24 hours.", + "This run measured the single-engine path; DeltaSearch was false in every measurement." + ], + "source_sha256": { + "pkg/acor/versioned.go": "550a2ce85dc272b1d992c0a943ffc90ea5e49486a71be7881fd83745d967e745", + "pkg/acor/versioned_scale_test.go": "1d50298c8f7194d296a222f93a0db3173b6386b0620f6b1699375cdc43b8dcfd", + "pkg/acor/versioned_million_test.go": "83f03bfa7029d7966917a358477b3fdedae24a1b0355d49794d47cbf92107e5f", + "pkg/acor/versioned_reuse.go": "ad18d950053af49c12966364ae4ee1cc86b1259fd030f34072832d6bd509e5a1", + "pkg/acor/versioned_snapshot.go": "bad1796954fb058b77bccdc0996a3c04c359d36cc728efbcc22b4422031ad47f", + "pkg/acor/versioned_write.go": "893dace7090bba07f55aeb69b81b0cc07541b3092b8e31b51c842fd6c0deb551" + }, + "runs": [ + { + "backend": "redis", + "n": 10000, + "kind": "diverse", + "repeat": 1, + "measurements": [ + { + "commit_ms": 29.382, + "commit_to_ready_ms": 140.096, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 43188224, + "n": 10000, + "operation": "initial_load", + "ready_ms": 169.479, + "received_bytes": 1014337, + "redis_bytes": 4551392, + "search_p50_ns": 500, + "search_p95_ns": 4500, + "search_p99_ns": 15875, + "search_samples": 169, + "sent_bytes": 5030965 + }, + { + "commit_ms": 140.734, + "commit_to_ready_ms": 0.054, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 44154880, + "n": 10000, + "operation": "identical_replace", + "ready_ms": 140.788, + "received_bytes": 835175, + "redis_bytes": 3905488, + "search_p50_ns": 2542, + "search_p95_ns": 8250, + "search_p99_ns": 10959, + "search_samples": 140, + "sent_bytes": 622006 + }, + { + "commit_ms": 5.482, + "commit_to_ready_ms": 30.103, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 47513600, + "n": 10000, + "operation": "add_1_repeat_0", + "ready_ms": 35.586, + "received_bytes": 1286634, + "redis_bytes": 5197136, + "search_p50_ns": 1791, + "search_p95_ns": 7500, + "search_p99_ns": 8208, + "search_samples": 32, + "sent_bytes": 648246 + }, + { + "commit_ms": 5.424, + "commit_to_ready_ms": 30.106, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 50561024, + "n": 10000, + "operation": "remove_1_repeat_0", + "ready_ms": 35.53, + "received_bytes": 1286562, + "redis_bytes": 5840128, + "search_p50_ns": 1792, + "search_p95_ns": 13375, + "search_p99_ns": 49125, + "search_samples": 31, + "sent_bytes": 648127 + }, + { + "commit_ms": 5.187, + "commit_to_ready_ms": 30.059, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 50626560, + "n": 10000, + "operation": "add_1_repeat_1", + "ready_ms": 35.246, + "received_bytes": 1286498, + "redis_bytes": 6496864, + "search_p50_ns": 2209, + "search_p95_ns": 8708, + "search_p99_ns": 11750, + "search_samples": 31, + "sent_bytes": 648113 + }, + { + "commit_ms": 5.579, + "commit_to_ready_ms": 30.143, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 50659328, + "n": 10000, + "operation": "remove_1_repeat_1", + "ready_ms": 35.723, + "received_bytes": 1286499, + "redis_bytes": 7153152, + "search_p50_ns": 2334, + "search_p95_ns": 7833, + "search_p99_ns": 9167, + "search_samples": 31, + "sent_bytes": 648095 + }, + { + "commit_ms": 5.072, + "commit_to_ready_ms": 20.058, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 50692096, + "n": 10000, + "operation": "add_1_repeat_2", + "ready_ms": 25.13, + "received_bytes": 1286627, + "redis_bytes": 7809888, + "search_p50_ns": 2500, + "search_p95_ns": 8541, + "search_p99_ns": 11292, + "search_samples": 22, + "sent_bytes": 648178 + }, + { + "commit_ms": 5.557, + "commit_to_ready_ms": 30.125, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52019200, + "n": 10000, + "operation": "remove_1_repeat_2", + "ready_ms": 35.683, + "received_bytes": 1286628, + "redis_bytes": 8466192, + "search_p50_ns": 1875, + "search_p95_ns": 11125, + "search_p99_ns": 12208, + "search_samples": 30, + "sent_bytes": 648159 + }, + { + "commit_ms": 5.847, + "commit_to_ready_ms": 30.165, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52068352, + "n": 10000, + "operation": "add_1", + "ready_ms": 36.012, + "received_bytes": 1286629, + "redis_bytes": 9123104, + "search_p50_ns": 1958, + "search_p95_ns": 12458, + "search_p99_ns": 14333, + "search_samples": 31, + "sent_bytes": 648180 + }, + { + "commit_ms": 5.753, + "commit_to_ready_ms": 20.134, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52133888, + "n": 10000, + "operation": "remove_1", + "ready_ms": 25.887, + "received_bytes": 1286632, + "redis_bytes": 9779408, + "search_p50_ns": 2000, + "search_p95_ns": 4541, + "search_p99_ns": 4541, + "search_samples": 21, + "sent_bytes": 648161 + }, + { + "commit_ms": 45.834, + "commit_to_ready_ms": 50.147, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52183040, + "n": 10000, + "operation": "add_1000", + "ready_ms": 95.981, + "received_bytes": 1404296, + "redis_bytes": 10878320, + "search_p50_ns": 1625, + "search_p95_ns": 12208, + "search_p99_ns": 27833, + "search_samples": 95, + "sent_bytes": 1858957 + }, + { + "commit_ms": 29.122, + "commit_to_ready_ms": 40.039, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52232192, + "n": 10000, + "operation": "remove_1000", + "ready_ms": 69.161, + "received_bytes": 1404036, + "redis_bytes": 11530224, + "search_p50_ns": 1834, + "search_p95_ns": 6042, + "search_p99_ns": 11625, + "search_samples": 67, + "sent_bytes": 1763531 + }, + { + "commit_ms": 7.365, + "commit_to_ready_ms": 30.053, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52248576, + "n": 10000, + "operation": "add_100", + "ready_ms": 37.419, + "received_bytes": 1299614, + "redis_bytes": 12226080, + "search_p50_ns": 1709, + "search_p95_ns": 7042, + "search_p99_ns": 7291, + "search_samples": 33, + "sent_bytes": 782695 + }, + { + "commit_ms": 7.322, + "commit_to_ready_ms": 40.06, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 53067776, + "n": 10000, + "operation": "remove_100", + "ready_ms": 47.382, + "received_bytes": 1299582, + "redis_bytes": 12882016, + "search_p50_ns": 2042, + "search_p95_ns": 6959, + "search_p99_ns": 7667, + "search_samples": 44, + "sent_bytes": 771712 + }, + { + "commit_ms": 109.652, + "commit_to_ready_ms": 100.134, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 53215232, + "n": 10000, + "operation": "full_replace", + "ready_ms": 209.787, + "received_bytes": 1705516, + "redis_bytes": 15109792, + "search_p50_ns": 1542, + "search_p95_ns": 5292, + "search_p99_ns": 7084, + "search_samples": 196, + "sent_bytes": 5707576 + } + ], + "startup_ms": 133.983, + "prune": { + "ms": 13.061, + "generations": 14, + "chunks": 4719, + "redis_bytes": 4580832 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=10000 kind=diverse seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469771409243 uptime_in_seconds:60 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084875 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 10000, + "kind": "diverse", + "repeat": 2, + "measurements": [ + { + "commit_ms": 30.409, + "commit_to_ready_ms": 100.06, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 42647552, + "n": 10000, + "operation": "initial_load", + "ready_ms": 130.47, + "received_bytes": 1014374, + "redis_bytes": 4541792, + "search_p50_ns": 500, + "search_p95_ns": 2875, + "search_p99_ns": 15292, + "search_samples": 127, + "sent_bytes": 5030965 + }, + { + "commit_ms": 71.604, + "commit_to_ready_ms": 0.016, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 43827200, + "n": 10000, + "operation": "identical_replace", + "ready_ms": 71.621, + "received_bytes": 835435, + "redis_bytes": 3925600, + "search_p50_ns": 1500, + "search_p95_ns": 2375, + "search_p99_ns": 2542, + "search_samples": 66, + "sent_bytes": 622151 + }, + { + "commit_ms": 5.182, + "commit_to_ready_ms": 30.049, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 47628288, + "n": 10000, + "operation": "add_1_repeat_0", + "ready_ms": 35.231, + "received_bytes": 1286593, + "redis_bytes": 5217248, + "search_p50_ns": 2875, + "search_p95_ns": 22625, + "search_p99_ns": 22916, + "search_samples": 30, + "sent_bytes": 648145 + }, + { + "commit_ms": 5.034, + "commit_to_ready_ms": 20.16, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 50675712, + "n": 10000, + "operation": "remove_1_repeat_0", + "ready_ms": 25.194, + "received_bytes": 1286593, + "redis_bytes": 5858160, + "search_p50_ns": 2292, + "search_p95_ns": 7667, + "search_p99_ns": 7667, + "search_samples": 21, + "sent_bytes": 648127 + }, + { + "commit_ms": 4.748, + "commit_to_ready_ms": 30.142, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52166656, + "n": 10000, + "operation": "add_1_repeat_1", + "ready_ms": 34.891, + "received_bytes": 1286529, + "redis_bytes": 6514912, + "search_p50_ns": 2000, + "search_p95_ns": 6417, + "search_p99_ns": 6917, + "search_samples": 29, + "sent_bytes": 648113 + }, + { + "commit_ms": 5.049, + "commit_to_ready_ms": 30.149, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52199424, + "n": 10000, + "operation": "remove_1_repeat_1", + "ready_ms": 35.198, + "received_bytes": 1286530, + "redis_bytes": 7171168, + "search_p50_ns": 2166, + "search_p95_ns": 7125, + "search_p99_ns": 16000, + "search_samples": 31, + "sent_bytes": 648095 + }, + { + "commit_ms": 4.807, + "commit_to_ready_ms": 30.156, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52215808, + "n": 10000, + "operation": "add_1_repeat_2", + "ready_ms": 34.963, + "received_bytes": 1286658, + "redis_bytes": 7812560, + "search_p50_ns": 2125, + "search_p95_ns": 7000, + "search_p99_ns": 7667, + "search_samples": 32, + "sent_bytes": 648178 + }, + { + "commit_ms": 6.343, + "commit_to_ready_ms": 20.086, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52215808, + "n": 10000, + "operation": "remove_1_repeat_2", + "ready_ms": 26.429, + "received_bytes": 1286659, + "redis_bytes": 8468896, + "search_p50_ns": 2500, + "search_p95_ns": 6667, + "search_p99_ns": 7000, + "search_samples": 22, + "sent_bytes": 648159 + }, + { + "commit_ms": 6.147, + "commit_to_ready_ms": 30.087, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52264960, + "n": 10000, + "operation": "add_1", + "ready_ms": 36.235, + "received_bytes": 1286661, + "redis_bytes": 9125792, + "search_p50_ns": 4000, + "search_p95_ns": 9584, + "search_p99_ns": 21208, + "search_samples": 31, + "sent_bytes": 648180 + }, + { + "commit_ms": 6.512, + "commit_to_ready_ms": 20.189, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52330496, + "n": 10000, + "operation": "remove_1", + "ready_ms": 26.701, + "received_bytes": 1286662, + "redis_bytes": 9782112, + "search_p50_ns": 2292, + "search_p95_ns": 7750, + "search_p99_ns": 7875, + "search_samples": 22, + "sent_bytes": 648161 + }, + { + "commit_ms": 42.348, + "commit_to_ready_ms": 50.057, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52363264, + "n": 10000, + "operation": "add_1000", + "ready_ms": 92.405, + "received_bytes": 1404328, + "redis_bytes": 11515968, + "search_p50_ns": 1542, + "search_p95_ns": 5709, + "search_p99_ns": 7500, + "search_samples": 88, + "sent_bytes": 1858957 + }, + { + "commit_ms": 27.523, + "commit_to_ready_ms": 40.086, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52461568, + "n": 10000, + "operation": "remove_1000", + "ready_ms": 67.609, + "received_bytes": 1404066, + "redis_bytes": 11534016, + "search_p50_ns": 1750, + "search_p95_ns": 6584, + "search_p99_ns": 7208, + "search_samples": 62, + "sent_bytes": 1763531 + }, + { + "commit_ms": 7.274, + "commit_to_ready_ms": 20.055, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52477952, + "n": 10000, + "operation": "add_100", + "ready_ms": 27.329, + "received_bytes": 1299645, + "redis_bytes": 12229664, + "search_p50_ns": 1709, + "search_p95_ns": 5167, + "search_p99_ns": 6292, + "search_samples": 23, + "sent_bytes": 782695 + }, + { + "commit_ms": 7.57, + "commit_to_ready_ms": 30.113, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52477952, + "n": 10000, + "operation": "remove_100", + "ready_ms": 37.683, + "received_bytes": 1299613, + "redis_bytes": 12887648, + "search_p50_ns": 2666, + "search_p95_ns": 7750, + "search_p99_ns": 11375, + "search_samples": 34, + "sent_bytes": 771712 + }, + { + "commit_ms": 100.894, + "commit_to_ready_ms": 100.178, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 57360384, + "n": 10000, + "operation": "full_replace", + "ready_ms": 201.073, + "received_bytes": 1705547, + "redis_bytes": 15134384, + "search_p50_ns": 1500, + "search_p95_ns": 6458, + "search_p99_ns": 8250, + "search_samples": 184, + "sent_bytes": 5707576 + } + ], + "startup_ms": 75.944, + "prune": { + "ms": 13.241, + "generations": 14, + "chunks": 4719, + "redis_bytes": 4602528 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=10000 kind=diverse seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469838258940 uptime_in_seconds:127 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084942 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 10000, + "kind": "diverse", + "repeat": 3, + "measurements": [ + { + "commit_ms": 29.138, + "commit_to_ready_ms": 100.045, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 42172416, + "n": 10000, + "operation": "initial_load", + "ready_ms": 129.183, + "received_bytes": 1014373, + "redis_bytes": 4527968, + "search_p50_ns": 417, + "search_p95_ns": 4167, + "search_p99_ns": 8708, + "search_samples": 119, + "sent_bytes": 5030965 + }, + { + "commit_ms": 70.374, + "commit_to_ready_ms": 0.019, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 43696128, + "n": 10000, + "operation": "identical_replace", + "ready_ms": 70.393, + "received_bytes": 835440, + "redis_bytes": 3914832, + "search_p50_ns": 1458, + "search_p95_ns": 2000, + "search_p99_ns": 2250, + "search_samples": 59, + "sent_bytes": 622151 + }, + { + "commit_ms": 4.709, + "commit_to_ready_ms": 30.119, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 48513024, + "n": 10000, + "operation": "add_1_repeat_0", + "ready_ms": 34.828, + "received_bytes": 1286596, + "redis_bytes": 5206512, + "search_p50_ns": 2000, + "search_p95_ns": 10083, + "search_p99_ns": 21750, + "search_samples": 32, + "sent_bytes": 648145 + }, + { + "commit_ms": 4.869, + "commit_to_ready_ms": 20.149, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 49020928, + "n": 10000, + "operation": "remove_1_repeat_0", + "ready_ms": 25.018, + "received_bytes": 1286596, + "redis_bytes": 5862848, + "search_p50_ns": 3667, + "search_p95_ns": 12667, + "search_p99_ns": 12667, + "search_samples": 21, + "sent_bytes": 648127 + }, + { + "commit_ms": 4.768, + "commit_to_ready_ms": 30.142, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 49086464, + "n": 10000, + "operation": "add_1_repeat_1", + "ready_ms": 34.91, + "received_bytes": 1286531, + "redis_bytes": 6519600, + "search_p50_ns": 2125, + "search_p95_ns": 6959, + "search_p99_ns": 7500, + "search_samples": 30, + "sent_bytes": 648113 + }, + { + "commit_ms": 4.992, + "commit_to_ready_ms": 30.183, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 50118656, + "n": 10000, + "operation": "remove_1_repeat_1", + "ready_ms": 35.176, + "received_bytes": 1286534, + "redis_bytes": 7175888, + "search_p50_ns": 5083, + "search_p95_ns": 7459, + "search_p99_ns": 7750, + "search_samples": 31, + "sent_bytes": 648095 + }, + { + "commit_ms": 4.898, + "commit_to_ready_ms": 30.073, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 50167808, + "n": 10000, + "operation": "add_1_repeat_2", + "ready_ms": 34.971, + "received_bytes": 1286662, + "redis_bytes": 7832624, + "search_p50_ns": 2250, + "search_p95_ns": 6792, + "search_p99_ns": 8791, + "search_samples": 29, + "sent_bytes": 648178 + }, + { + "commit_ms": 6.047, + "commit_to_ready_ms": 20.132, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 51642368, + "n": 10000, + "operation": "remove_1_repeat_2", + "ready_ms": 26.18, + "received_bytes": 1286663, + "redis_bytes": 8473584, + "search_p50_ns": 3042, + "search_p95_ns": 8625, + "search_p99_ns": 8625, + "search_samples": 21, + "sent_bytes": 648159 + }, + { + "commit_ms": 6.377, + "commit_to_ready_ms": 30.091, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 51658752, + "n": 10000, + "operation": "add_1", + "ready_ms": 36.469, + "received_bytes": 1286664, + "redis_bytes": 9130480, + "search_p50_ns": 5292, + "search_p95_ns": 6667, + "search_p99_ns": 7166, + "search_samples": 33, + "sent_bytes": 648180 + }, + { + "commit_ms": 7.214, + "commit_to_ready_ms": 30.089, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 51658752, + "n": 10000, + "operation": "remove_1", + "ready_ms": 37.303, + "received_bytes": 1286667, + "redis_bytes": 9786688, + "search_p50_ns": 5000, + "search_p95_ns": 7000, + "search_p99_ns": 16792, + "search_samples": 33, + "sent_bytes": 648161 + }, + { + "commit_ms": 41.892, + "commit_to_ready_ms": 50.065, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 52346880, + "n": 10000, + "operation": "add_1000", + "ready_ms": 91.958, + "received_bytes": 1404331, + "redis_bytes": 10885440, + "search_p50_ns": 1500, + "search_p95_ns": 3334, + "search_p99_ns": 17083, + "search_samples": 87, + "sent_bytes": 1858957 + }, + { + "commit_ms": 26.885, + "commit_to_ready_ms": 40.136, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 53346304, + "n": 10000, + "operation": "remove_1000", + "ready_ms": 67.022, + "received_bytes": 1404070, + "redis_bytes": 11537312, + "search_p50_ns": 1708, + "search_p95_ns": 7334, + "search_p99_ns": 9833, + "search_samples": 61, + "sent_bytes": 1763531 + }, + { + "commit_ms": 7.25, + "commit_to_ready_ms": 20.055, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 56311808, + "n": 10000, + "operation": "add_100", + "ready_ms": 27.305, + "received_bytes": 1299649, + "redis_bytes": 12233152, + "search_p50_ns": 2041, + "search_p95_ns": 7167, + "search_p99_ns": 23542, + "search_samples": 25, + "sent_bytes": 782695 + }, + { + "commit_ms": 7.12, + "commit_to_ready_ms": 40.052, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 56328192, + "n": 10000, + "operation": "remove_100", + "ready_ms": 47.173, + "received_bytes": 1299617, + "redis_bytes": 12889088, + "search_p50_ns": 1958, + "search_p95_ns": 7167, + "search_p99_ns": 7417, + "search_samples": 42, + "sent_bytes": 771712 + }, + { + "commit_ms": 105.527, + "commit_to_ready_ms": 100.089, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 56590336, + "n": 10000, + "operation": "full_replace", + "ready_ms": 205.616, + "received_bytes": 1705551, + "redis_bytes": 15135616, + "search_p50_ns": 1542, + "search_p95_ns": 5500, + "search_p99_ns": 7458, + "search_samples": 191, + "sent_bytes": 5707576 + } + ], + "startup_ms": 72.156, + "prune": { + "ms": 13.252, + "generations": 14, + "chunks": 4719, + "redis_bytes": 4607600 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=10000 kind=diverse seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469904564142 uptime_in_seconds:193 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11085008 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 10000, + "kind": "korean", + "repeat": 1, + "measurements": [ + { + "commit_ms": 30.815, + "commit_to_ready_ms": 100.161, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 50184192, + "n": 10000, + "operation": "initial_load", + "ready_ms": 130.976, + "received_bytes": 1220562, + "redis_bytes": 4723120, + "search_p50_ns": 708, + "search_p95_ns": 2792, + "search_p99_ns": 4291, + "search_samples": 111, + "sent_bytes": 5273096 + }, + { + "commit_ms": 74.092, + "commit_to_ready_ms": 0.018, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 50937856, + "n": 10000, + "operation": "identical_replace", + "ready_ms": 74.11, + "received_bytes": 1041505, + "redis_bytes": 4125360, + "search_p50_ns": 1916, + "search_p95_ns": 3458, + "search_p99_ns": 7166, + "search_samples": 54, + "sent_bytes": 627463 + }, + { + "commit_ms": 4.778, + "commit_to_ready_ms": 30.132, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 67059712, + "n": 10000, + "operation": "add_1_repeat_0", + "ready_ms": 34.91, + "received_bytes": 1294702, + "redis_bytes": 5416944, + "search_p50_ns": 2250, + "search_p95_ns": 8833, + "search_p99_ns": 8875, + "search_samples": 32, + "sent_bytes": 652214 + }, + { + "commit_ms": 4.758, + "commit_to_ready_ms": 30.123, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 70041600, + "n": 10000, + "operation": "remove_1_repeat_0", + "ready_ms": 34.882, + "received_bytes": 1294702, + "redis_bytes": 6057888, + "search_p50_ns": 2167, + "search_p95_ns": 8458, + "search_p99_ns": 10500, + "search_samples": 29, + "sent_bytes": 652196 + }, + { + "commit_ms": 4.73, + "commit_to_ready_ms": 20.119, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 71450624, + "n": 10000, + "operation": "add_1_repeat_1", + "ready_ms": 24.849, + "received_bytes": 1294920, + "redis_bytes": 6714800, + "search_p50_ns": 2167, + "search_p95_ns": 10750, + "search_p99_ns": 10750, + "search_samples": 20, + "sent_bytes": 652323 + }, + { + "commit_ms": 4.571, + "commit_to_ready_ms": 30.12, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 71483392, + "n": 10000, + "operation": "remove_1_repeat_1", + "ready_ms": 34.692, + "received_bytes": 1294921, + "redis_bytes": 7371088, + "search_p50_ns": 2541, + "search_p95_ns": 7875, + "search_p99_ns": 7916, + "search_samples": 29, + "sent_bytes": 652305 + }, + { + "commit_ms": 4.689, + "commit_to_ready_ms": 30.111, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 73728000, + "n": 10000, + "operation": "add_1_repeat_2", + "ready_ms": 34.8, + "received_bytes": 1294848, + "redis_bytes": 8012512, + "search_p50_ns": 3083, + "search_p95_ns": 9375, + "search_p99_ns": 9500, + "search_samples": 30, + "sent_bytes": 652287 + }, + { + "commit_ms": 5.876, + "commit_to_ready_ms": 20.139, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 73744384, + "n": 10000, + "operation": "remove_1_repeat_2", + "ready_ms": 26.015, + "received_bytes": 1294849, + "redis_bytes": 8668864, + "search_p50_ns": 2708, + "search_p95_ns": 9834, + "search_p99_ns": 9834, + "search_samples": 20, + "sent_bytes": 652269 + }, + { + "commit_ms": 6.556, + "commit_to_ready_ms": 40.123, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 73744384, + "n": 10000, + "operation": "add_1", + "ready_ms": 46.679, + "received_bytes": 1294850, + "redis_bytes": 9325808, + "search_p50_ns": 3333, + "search_p95_ns": 9000, + "search_p99_ns": 20750, + "search_samples": 42, + "sent_bytes": 652289 + }, + { + "commit_ms": 6.53, + "commit_to_ready_ms": 20.116, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 73744384, + "n": 10000, + "operation": "remove_1", + "ready_ms": 26.647, + "received_bytes": 1294853, + "redis_bytes": 9982080, + "search_p50_ns": 2709, + "search_p95_ns": 10583, + "search_p99_ns": 10667, + "search_samples": 22, + "sent_bytes": 652271 + }, + { + "commit_ms": 42.149, + "commit_to_ready_ms": 50.031, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 75612160, + "n": 10000, + "operation": "add_1000", + "ready_ms": 92.181, + "received_bytes": 1500035, + "redis_bytes": 11131168, + "search_p50_ns": 1875, + "search_p95_ns": 8417, + "search_p99_ns": 11500, + "search_samples": 87, + "sent_bytes": 1906115 + }, + { + "commit_ms": 27.148, + "commit_to_ready_ms": 50.037, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 75661312, + "n": 10000, + "operation": "remove_1000", + "ready_ms": 77.185, + "received_bytes": 1499747, + "redis_bytes": 12418288, + "search_p50_ns": 2125, + "search_p95_ns": 8375, + "search_p99_ns": 9416, + "search_samples": 69, + "sent_bytes": 1803066 + }, + { + "commit_ms": 6.861, + "commit_to_ready_ms": 20.147, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 76251136, + "n": 10000, + "operation": "add_100", + "ready_ms": 27.008, + "received_bytes": 1317755, + "redis_bytes": 12466160, + "search_p50_ns": 2917, + "search_p95_ns": 8458, + "search_p99_ns": 8458, + "search_samples": 21, + "sent_bytes": 791659 + }, + { + "commit_ms": 7.088, + "commit_to_ready_ms": 30.091, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 76300288, + "n": 10000, + "operation": "remove_100", + "ready_ms": 37.179, + "received_bytes": 1317719, + "redis_bytes": 13122224, + "search_p50_ns": 3416, + "search_p95_ns": 9209, + "search_p99_ns": 14875, + "search_samples": 31, + "sent_bytes": 779595 + }, + { + "commit_ms": 107.688, + "commit_to_ready_ms": 100.131, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 85688320, + "n": 10000, + "operation": "full_replace", + "ready_ms": 207.82, + "received_bytes": 2112234, + "redis_bytes": 15605824, + "search_p50_ns": 1875, + "search_p95_ns": 6209, + "search_p99_ns": 30083, + "search_samples": 185, + "sent_bytes": 5905622 + } + ], + "startup_ms": 76.824, + "prune": { + "ms": 13.452, + "generations": 14, + "chunks": 4751, + "redis_bytes": 4818944 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=10000 kind=korean seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469772686904 uptime_in_seconds:61 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084876 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 10000, + "kind": "korean", + "repeat": 2, + "measurements": [ + { + "commit_ms": 59.355, + "commit_to_ready_ms": 110.107, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 52396032, + "n": 10000, + "operation": "initial_load", + "ready_ms": 169.462, + "received_bytes": 1220596, + "redis_bytes": 4723472, + "search_p50_ns": 1584, + "search_p95_ns": 5084, + "search_p99_ns": 16291, + "search_samples": 161, + "sent_bytes": 5273096 + }, + { + "commit_ms": 86.361, + "commit_to_ready_ms": 0.016, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 53248000, + "n": 10000, + "operation": "identical_replace", + "ready_ms": 86.378, + "received_bytes": 1041530, + "redis_bytes": 4125712, + "search_p50_ns": 2167, + "search_p95_ns": 12875, + "search_p99_ns": 58709, + "search_samples": 84, + "sent_bytes": 627463 + }, + { + "commit_ms": 5.911, + "commit_to_ready_ms": 20.111, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 62799872, + "n": 10000, + "operation": "add_1_repeat_0", + "ready_ms": 26.022, + "received_bytes": 1294727, + "redis_bytes": 5417280, + "search_p50_ns": 4750, + "search_p95_ns": 11584, + "search_p99_ns": 11584, + "search_samples": 21, + "sent_bytes": 652214 + }, + { + "commit_ms": 5.32, + "commit_to_ready_ms": 30.077, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 62849024, + "n": 10000, + "operation": "remove_1_repeat_0", + "ready_ms": 35.398, + "received_bytes": 1294732, + "redis_bytes": 6058224, + "search_p50_ns": 2375, + "search_p95_ns": 3459, + "search_p99_ns": 4625, + "search_samples": 33, + "sent_bytes": 652196 + }, + { + "commit_ms": 5.232, + "commit_to_ready_ms": 30.043, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 66322432, + "n": 10000, + "operation": "add_1_repeat_1", + "ready_ms": 35.275, + "received_bytes": 1294949, + "redis_bytes": 6715152, + "search_p50_ns": 2125, + "search_p95_ns": 7500, + "search_p99_ns": 8750, + "search_samples": 35, + "sent_bytes": 652323 + }, + { + "commit_ms": 4.877, + "commit_to_ready_ms": 30.14, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 71614464, + "n": 10000, + "operation": "remove_1_repeat_1", + "ready_ms": 35.018, + "received_bytes": 1294950, + "redis_bytes": 7371424, + "search_p50_ns": 2292, + "search_p95_ns": 5875, + "search_p99_ns": 5958, + "search_samples": 29, + "sent_bytes": 652305 + }, + { + "commit_ms": 4.984, + "commit_to_ready_ms": 40.151, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 71630848, + "n": 10000, + "operation": "add_1_repeat_2", + "ready_ms": 45.136, + "received_bytes": 1294877, + "redis_bytes": 8015904, + "search_p50_ns": 2042, + "search_p95_ns": 9333, + "search_p99_ns": 19750, + "search_samples": 43, + "sent_bytes": 652287 + }, + { + "commit_ms": 6.096, + "commit_to_ready_ms": 20.057, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 71663616, + "n": 10000, + "operation": "remove_1_repeat_2", + "ready_ms": 26.153, + "received_bytes": 1294878, + "redis_bytes": 8672240, + "search_p50_ns": 2333, + "search_p95_ns": 33292, + "search_p99_ns": 33292, + "search_samples": 21, + "sent_bytes": 652269 + }, + { + "commit_ms": 6.116, + "commit_to_ready_ms": 20.101, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 71696384, + "n": 10000, + "operation": "add_1", + "ready_ms": 26.218, + "received_bytes": 1294879, + "redis_bytes": 9329120, + "search_p50_ns": 2333, + "search_p95_ns": 6000, + "search_p99_ns": 14208, + "search_samples": 22, + "sent_bytes": 652289 + }, + { + "commit_ms": 6.238, + "commit_to_ready_ms": 40.053, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 71712768, + "n": 10000, + "operation": "remove_1", + "ready_ms": 46.291, + "received_bytes": 1294882, + "redis_bytes": 9985440, + "search_p50_ns": 2042, + "search_p95_ns": 10709, + "search_p99_ns": 14916, + "search_samples": 42, + "sent_bytes": 652271 + }, + { + "commit_ms": 40.894, + "commit_to_ready_ms": 60.14, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 78348288, + "n": 10000, + "operation": "add_1000", + "ready_ms": 101.034, + "received_bytes": 1500137, + "redis_bytes": 11133136, + "search_p50_ns": 1959, + "search_p95_ns": 3625, + "search_p99_ns": 7750, + "search_samples": 98, + "sent_bytes": 1906216 + }, + { + "commit_ms": 27.244, + "commit_to_ready_ms": 40.047, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 78659584, + "n": 10000, + "operation": "remove_1000", + "ready_ms": 67.292, + "received_bytes": 1499776, + "redis_bytes": 11785392, + "search_p50_ns": 2167, + "search_p95_ns": 9625, + "search_p99_ns": 14417, + "search_samples": 61, + "sent_bytes": 1803066 + }, + { + "commit_ms": 7.502, + "commit_to_ready_ms": 30.079, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 78692352, + "n": 10000, + "operation": "add_100", + "ready_ms": 37.581, + "received_bytes": 1317784, + "redis_bytes": 12486704, + "search_p50_ns": 2750, + "search_p95_ns": 9416, + "search_p99_ns": 12625, + "search_samples": 33, + "sent_bytes": 791659 + }, + { + "commit_ms": 11.399, + "commit_to_ready_ms": 40.101, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 78692352, + "n": 10000, + "operation": "remove_100", + "ready_ms": 51.501, + "received_bytes": 1317748, + "redis_bytes": 13142752, + "search_p50_ns": 2583, + "search_p95_ns": 8875, + "search_p99_ns": 9250, + "search_samples": 46, + "sent_bytes": 779595 + }, + { + "commit_ms": 116.321, + "commit_to_ready_ms": 90.074, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 85770240, + "n": 10000, + "operation": "full_replace", + "ready_ms": 206.396, + "received_bytes": 2112263, + "redis_bytes": 15605088, + "search_p50_ns": 1875, + "search_p95_ns": 3459, + "search_p99_ns": 12750, + "search_samples": 199, + "sent_bytes": 5905622 + } + ], + "startup_ms": 77.851, + "prune": { + "ms": 13.606, + "generations": 14, + "chunks": 4751, + "redis_bytes": 4818976 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=10000 kind=korean seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469839318072 uptime_in_seconds:128 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084943 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 10000, + "kind": "korean", + "repeat": 3, + "measurements": [ + { + "commit_ms": 31.207, + "commit_to_ready_ms": 100.039, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 50626560, + "n": 10000, + "operation": "initial_load", + "ready_ms": 131.247, + "received_bytes": 1220600, + "redis_bytes": 4760480, + "search_p50_ns": 750, + "search_p95_ns": 3208, + "search_p99_ns": 18917, + "search_samples": 123, + "sent_bytes": 5273096 + }, + { + "commit_ms": 73.358, + "commit_to_ready_ms": 0.014, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 51937280, + "n": 10000, + "operation": "identical_replace", + "ready_ms": 73.372, + "received_bytes": 1041539, + "redis_bytes": 4114592, + "search_p50_ns": 2125, + "search_p95_ns": 3209, + "search_p99_ns": 8291, + "search_samples": 65, + "sent_bytes": 627463 + }, + { + "commit_ms": 4.765, + "commit_to_ready_ms": 30.145, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 68501504, + "n": 10000, + "operation": "add_1_repeat_0", + "ready_ms": 34.911, + "received_bytes": 1294736, + "redis_bytes": 5406160, + "search_p50_ns": 2250, + "search_p95_ns": 8083, + "search_p99_ns": 10584, + "search_samples": 31, + "sent_bytes": 652214 + }, + { + "commit_ms": 4.745, + "commit_to_ready_ms": 20.09, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 71467008, + "n": 10000, + "operation": "remove_1_repeat_0", + "ready_ms": 24.835, + "received_bytes": 1294736, + "redis_bytes": 6062432, + "search_p50_ns": 2375, + "search_p95_ns": 10125, + "search_p99_ns": 10125, + "search_samples": 21, + "sent_bytes": 652196 + }, + { + "commit_ms": 4.826, + "commit_to_ready_ms": 30.095, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 72548352, + "n": 10000, + "operation": "add_1_repeat_1", + "ready_ms": 34.921, + "received_bytes": 1294953, + "redis_bytes": 6706064, + "search_p50_ns": 2459, + "search_p95_ns": 8791, + "search_p99_ns": 11459, + "search_samples": 29, + "sent_bytes": 652323 + }, + { + "commit_ms": 4.741, + "commit_to_ready_ms": 30.153, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 72564736, + "n": 10000, + "operation": "remove_1_repeat_1", + "ready_ms": 34.895, + "received_bytes": 1294954, + "redis_bytes": 7362352, + "search_p50_ns": 2500, + "search_p95_ns": 35625, + "search_p99_ns": 40542, + "search_samples": 28, + "sent_bytes": 652305 + }, + { + "commit_ms": 5.032, + "commit_to_ready_ms": 30.119, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 72613888, + "n": 10000, + "operation": "add_1_repeat_2", + "ready_ms": 35.152, + "received_bytes": 1294881, + "redis_bytes": 8019168, + "search_p50_ns": 2625, + "search_p95_ns": 8500, + "search_p99_ns": 8667, + "search_samples": 32, + "sent_bytes": 652287 + }, + { + "commit_ms": 5.607, + "commit_to_ready_ms": 20.111, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 72613888, + "n": 10000, + "operation": "remove_1_repeat_2", + "ready_ms": 25.719, + "received_bytes": 1294882, + "redis_bytes": 8675488, + "search_p50_ns": 4208, + "search_p95_ns": 8583, + "search_p99_ns": 9042, + "search_samples": 22, + "sent_bytes": 652269 + }, + { + "commit_ms": 6.579, + "commit_to_ready_ms": 30.061, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 72630272, + "n": 10000, + "operation": "add_1", + "ready_ms": 36.64, + "received_bytes": 1294883, + "redis_bytes": 9332416, + "search_p50_ns": 6583, + "search_p95_ns": 18834, + "search_p99_ns": 22875, + "search_samples": 32, + "sent_bytes": 652289 + }, + { + "commit_ms": 7.089, + "commit_to_ready_ms": 30.062, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 72663040, + "n": 10000, + "operation": "remove_1", + "ready_ms": 37.152, + "received_bytes": 1294886, + "redis_bytes": 10623584, + "search_p50_ns": 2375, + "search_p95_ns": 9791, + "search_p99_ns": 13875, + "search_samples": 34, + "sent_bytes": 652271 + }, + { + "commit_ms": 44.407, + "commit_to_ready_ms": 50.065, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 72695808, + "n": 10000, + "operation": "add_1000", + "ready_ms": 94.473, + "received_bytes": 1500070, + "redis_bytes": 11773536, + "search_p50_ns": 1958, + "search_p95_ns": 8625, + "search_p99_ns": 13542, + "search_samples": 87, + "sent_bytes": 1906115 + }, + { + "commit_ms": 27.396, + "commit_to_ready_ms": 50.083, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 72761344, + "n": 10000, + "operation": "remove_1000", + "ready_ms": 77.479, + "received_bytes": 1499781, + "redis_bytes": 12427872, + "search_p50_ns": 2125, + "search_p95_ns": 8958, + "search_p99_ns": 15167, + "search_samples": 70, + "sent_bytes": 1803066 + }, + { + "commit_ms": 7.488, + "commit_to_ready_ms": 20.085, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 74498048, + "n": 10000, + "operation": "add_100", + "ready_ms": 27.573, + "received_bytes": 1317784, + "redis_bytes": 13129456, + "search_p50_ns": 2375, + "search_p95_ns": 14167, + "search_p99_ns": 25000, + "search_samples": 24, + "sent_bytes": 791659 + }, + { + "commit_ms": 7.476, + "commit_to_ready_ms": 30.08, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 79118336, + "n": 10000, + "operation": "remove_100", + "ready_ms": 37.556, + "received_bytes": 1317753, + "redis_bytes": 13130128, + "search_p50_ns": 3625, + "search_p95_ns": 30125, + "search_p99_ns": 74291, + "search_samples": 32, + "sent_bytes": 779595 + }, + { + "commit_ms": 110.776, + "commit_to_ready_ms": 90.053, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 79478784, + "n": 10000, + "operation": "full_replace", + "ready_ms": 200.829, + "received_bytes": 2112267, + "redis_bytes": 15611088, + "search_p50_ns": 1833, + "search_p95_ns": 4625, + "search_p99_ns": 8875, + "search_samples": 195, + "sent_bytes": 5905622 + } + ], + "startup_ms": 76.34, + "prune": { + "ms": 13.855, + "generations": 14, + "chunks": 4751, + "redis_bytes": 4823968 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=10000 kind=korean seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469905637436 uptime_in_seconds:194 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11085009 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 10000, + "kind": "shared", + "repeat": 1, + "measurements": [ + { + "commit_ms": 67.091, + "commit_to_ready_ms": 100.135, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 33783808, + "n": 10000, + "operation": "initial_load", + "ready_ms": 167.226, + "received_bytes": 1107955, + "redis_bytes": 4455008, + "search_p50_ns": 458, + "search_p95_ns": 4500, + "search_p99_ns": 8583, + "search_samples": 162, + "sent_bytes": 5147092 + }, + { + "commit_ms": 70.267, + "commit_to_ready_ms": 0.016, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 34684928, + "n": 10000, + "operation": "identical_replace", + "ready_ms": 70.284, + "received_bytes": 929000, + "redis_bytes": 3811168, + "search_p50_ns": 1541, + "search_p95_ns": 2000, + "search_p99_ns": 6958, + "search_samples": 60, + "sent_bytes": 625471 + }, + { + "commit_ms": 5.117, + "commit_to_ready_ms": 30.068, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35110912, + "n": 10000, + "operation": "add_1_repeat_0", + "ready_ms": 35.185, + "received_bytes": 1291743, + "redis_bytes": 5102896, + "search_p50_ns": 1708, + "search_p95_ns": 7083, + "search_p99_ns": 7417, + "search_samples": 35, + "sent_bytes": 650741 + }, + { + "commit_ms": 5.113, + "commit_to_ready_ms": 20.038, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35225600, + "n": 10000, + "operation": "remove_1_repeat_0", + "ready_ms": 25.152, + "received_bytes": 1291743, + "redis_bytes": 5759200, + "search_p50_ns": 1833, + "search_p95_ns": 6625, + "search_p99_ns": 6875, + "search_samples": 23, + "sent_bytes": 650723 + }, + { + "commit_ms": 5.022, + "commit_to_ready_ms": 30.121, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35274752, + "n": 10000, + "operation": "add_1_repeat_1", + "ready_ms": 35.143, + "received_bytes": 1291690, + "redis_bytes": 6400672, + "search_p50_ns": 2875, + "search_p95_ns": 7375, + "search_p99_ns": 7417, + "search_samples": 30, + "sent_bytes": 650715 + }, + { + "commit_ms": 5.029, + "commit_to_ready_ms": 30.094, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35307520, + "n": 10000, + "operation": "remove_1_repeat_1", + "ready_ms": 35.123, + "received_bytes": 1291692, + "redis_bytes": 7056960, + "search_p50_ns": 2042, + "search_p95_ns": 7041, + "search_p99_ns": 7125, + "search_samples": 30, + "sent_bytes": 650697 + }, + { + "commit_ms": 5.372, + "commit_to_ready_ms": 20.076, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35373056, + "n": 10000, + "operation": "add_1_repeat_2", + "ready_ms": 25.448, + "received_bytes": 1291641, + "redis_bytes": 7713696, + "search_p50_ns": 1792, + "search_p95_ns": 2792, + "search_p99_ns": 6708, + "search_samples": 23, + "sent_bytes": 650690 + }, + { + "commit_ms": 5.327, + "commit_to_ready_ms": 30.118, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35389440, + "n": 10000, + "operation": "remove_1_repeat_2", + "ready_ms": 35.446, + "received_bytes": 1291639, + "redis_bytes": 8369984, + "search_p50_ns": 2500, + "search_p95_ns": 6958, + "search_p99_ns": 9417, + "search_samples": 34, + "sent_bytes": 650672 + }, + { + "commit_ms": 7.251, + "commit_to_ready_ms": 20.103, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35422208, + "n": 10000, + "operation": "add_1", + "ready_ms": 27.355, + "received_bytes": 1291596, + "redis_bytes": 9026816, + "search_p50_ns": 2000, + "search_p95_ns": 6958, + "search_p99_ns": 7334, + "search_samples": 26, + "sent_bytes": 650667 + }, + { + "commit_ms": 9.041, + "commit_to_ready_ms": 20.128, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35438592, + "n": 10000, + "operation": "remove_1", + "ready_ms": 29.17, + "received_bytes": 1291597, + "redis_bytes": 9683120, + "search_p50_ns": 2375, + "search_p95_ns": 7084, + "search_p99_ns": 7459, + "search_samples": 28, + "sent_bytes": 650649 + }, + { + "commit_ms": 42.85, + "commit_to_ready_ms": 50.129, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35520512, + "n": 10000, + "operation": "add_1000", + "ready_ms": 92.979, + "received_bytes": 1453126, + "redis_bytes": 10802704, + "search_p50_ns": 1500, + "search_p95_ns": 6292, + "search_p99_ns": 11917, + "search_samples": 90, + "sent_bytes": 1881384 + }, + { + "commit_ms": 26.847, + "commit_to_ready_ms": 40.14, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35569664, + "n": 10000, + "operation": "remove_1000", + "ready_ms": 66.988, + "received_bytes": 1452787, + "redis_bytes": 11455136, + "search_p50_ns": 1667, + "search_p95_ns": 7167, + "search_p99_ns": 8833, + "search_samples": 60, + "sent_bytes": 1764101 + }, + { + "commit_ms": 6.947, + "commit_to_ready_ms": 30.149, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 37257216, + "n": 10000, + "operation": "add_100", + "ready_ms": 37.097, + "received_bytes": 1309827, + "redis_bytes": 12153312, + "search_p50_ns": 2167, + "search_p95_ns": 7208, + "search_p99_ns": 7458, + "search_samples": 33, + "sent_bytes": 787796 + }, + { + "commit_ms": 7.367, + "commit_to_ready_ms": 30.097, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 37257216, + "n": 10000, + "operation": "remove_100", + "ready_ms": 37.464, + "received_bytes": 1309795, + "redis_bytes": 12809280, + "search_p50_ns": 1792, + "search_p95_ns": 6459, + "search_p99_ns": 6541, + "search_samples": 36, + "sent_bytes": 776828 + }, + { + "commit_ms": 108.478, + "commit_to_ready_ms": 100.098, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 37945344, + "n": 10000, + "operation": "full_replace", + "ready_ms": 208.576, + "received_bytes": 1886255, + "redis_bytes": 15143632, + "search_p50_ns": 1583, + "search_p95_ns": 5792, + "search_p99_ns": 9792, + "search_samples": 190, + "sent_bytes": 5768860 + } + ], + "startup_ms": 70.966, + "prune": { + "ms": 13.076, + "generations": 14, + "chunks": 4739, + "redis_bytes": 4662448 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=10000 kind=shared seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469770312532 uptime_in_seconds:59 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084874 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 10000, + "kind": "shared", + "repeat": 2, + "measurements": [ + { + "commit_ms": 40.098, + "commit_to_ready_ms": 110.08, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 30621696, + "n": 10000, + "operation": "initial_load", + "ready_ms": 150.179, + "received_bytes": 1108054, + "redis_bytes": 4629904, + "search_p50_ns": 459, + "search_p95_ns": 4458, + "search_p99_ns": 10042, + "search_samples": 140, + "sent_bytes": 5147092 + }, + { + "commit_ms": 71.731, + "commit_to_ready_ms": 0.015, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 31637504, + "n": 10000, + "operation": "identical_replace", + "ready_ms": 71.747, + "received_bytes": 929034, + "redis_bytes": 4001424, + "search_p50_ns": 1583, + "search_p95_ns": 2459, + "search_p99_ns": 19833, + "search_samples": 63, + "sent_bytes": 625471 + }, + { + "commit_ms": 5.091, + "commit_to_ready_ms": 30.054, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 33046528, + "n": 10000, + "operation": "add_1_repeat_0", + "ready_ms": 35.146, + "received_bytes": 1291777, + "redis_bytes": 5277696, + "search_p50_ns": 1792, + "search_p95_ns": 7542, + "search_p99_ns": 7916, + "search_samples": 30, + "sent_bytes": 650741 + }, + { + "commit_ms": 5.019, + "commit_to_ready_ms": 20.135, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 34111488, + "n": 10000, + "operation": "remove_1_repeat_0", + "ready_ms": 25.154, + "received_bytes": 1291783, + "redis_bytes": 5934016, + "search_p50_ns": 2292, + "search_p95_ns": 7250, + "search_p99_ns": 7292, + "search_samples": 22, + "sent_bytes": 650723 + }, + { + "commit_ms": 5.592, + "commit_to_ready_ms": 20.118, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 34193408, + "n": 10000, + "operation": "add_1_repeat_1", + "ready_ms": 25.711, + "received_bytes": 1291730, + "redis_bytes": 6590816, + "search_p50_ns": 1875, + "search_p95_ns": 6625, + "search_p99_ns": 12458, + "search_samples": 22, + "sent_bytes": 650715 + }, + { + "commit_ms": 6.275, + "commit_to_ready_ms": 30.143, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 34832384, + "n": 10000, + "operation": "remove_1_repeat_1", + "ready_ms": 36.418, + "received_bytes": 1291731, + "redis_bytes": 7247088, + "search_p50_ns": 3667, + "search_p95_ns": 13709, + "search_p99_ns": 14833, + "search_samples": 31, + "sent_bytes": 650697 + }, + { + "commit_ms": 5.83, + "commit_to_ready_ms": 20.136, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 34848768, + "n": 10000, + "operation": "add_1_repeat_2", + "ready_ms": 25.967, + "received_bytes": 1291680, + "redis_bytes": 7891536, + "search_p50_ns": 3125, + "search_p95_ns": 12417, + "search_p99_ns": 12417, + "search_samples": 21, + "sent_bytes": 650690 + }, + { + "commit_ms": 8.135, + "commit_to_ready_ms": 30.032, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 34848768, + "n": 10000, + "operation": "remove_1_repeat_2", + "ready_ms": 38.167, + "received_bytes": 1291681, + "redis_bytes": 8547856, + "search_p50_ns": 2917, + "search_p95_ns": 14125, + "search_p99_ns": 17833, + "search_samples": 30, + "sent_bytes": 650672 + }, + { + "commit_ms": 6.782, + "commit_to_ready_ms": 20.125, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 34947072, + "n": 10000, + "operation": "add_1", + "ready_ms": 26.908, + "received_bytes": 1291632, + "redis_bytes": 9204672, + "search_p50_ns": 2084, + "search_p95_ns": 5416, + "search_p99_ns": 7333, + "search_samples": 24, + "sent_bytes": 650667 + }, + { + "commit_ms": 8.104, + "commit_to_ready_ms": 20.08, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 34963456, + "n": 10000, + "operation": "remove_1", + "ready_ms": 28.185, + "received_bytes": 1291635, + "redis_bytes": 9860992, + "search_p50_ns": 2375, + "search_p95_ns": 9250, + "search_p99_ns": 13625, + "search_samples": 26, + "sent_bytes": 650649 + }, + { + "commit_ms": 43.655, + "commit_to_ready_ms": 50.107, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35028992, + "n": 10000, + "operation": "add_1000", + "ready_ms": 93.763, + "received_bytes": 1453162, + "redis_bytes": 10980544, + "search_p50_ns": 1666, + "search_p95_ns": 6667, + "search_p99_ns": 7792, + "search_samples": 88, + "sent_bytes": 1881384 + }, + { + "commit_ms": 28.193, + "commit_to_ready_ms": 40.029, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35045376, + "n": 10000, + "operation": "remove_1000", + "ready_ms": 68.223, + "received_bytes": 1452824, + "redis_bytes": 11633008, + "search_p50_ns": 1750, + "search_p95_ns": 7625, + "search_p99_ns": 11541, + "search_samples": 63, + "sent_bytes": 1764101 + }, + { + "commit_ms": 7.657, + "commit_to_ready_ms": 30.104, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35078144, + "n": 10000, + "operation": "add_100", + "ready_ms": 37.762, + "received_bytes": 1309862, + "redis_bytes": 12331424, + "search_p50_ns": 1916, + "search_p95_ns": 7042, + "search_p99_ns": 8959, + "search_samples": 32, + "sent_bytes": 787796 + }, + { + "commit_ms": 8.42, + "commit_to_ready_ms": 30.125, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35160064, + "n": 10000, + "operation": "remove_100", + "ready_ms": 38.546, + "received_bytes": 1309830, + "redis_bytes": 12987424, + "search_p50_ns": 2125, + "search_p95_ns": 6917, + "search_p99_ns": 7458, + "search_samples": 35, + "sent_bytes": 776828 + }, + { + "commit_ms": 123.15, + "commit_to_ready_ms": 100.112, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 40615936, + "n": 10000, + "operation": "full_replace", + "ready_ms": 223.263, + "received_bytes": 1886290, + "redis_bytes": 15300464, + "search_p50_ns": 1709, + "search_p95_ns": 7625, + "search_p99_ns": 12584, + "search_samples": 215, + "sent_bytes": 5768860 + } + ], + "startup_ms": 72.457, + "prune": { + "ms": 13.271, + "generations": 14, + "chunks": 4739, + "redis_bytes": 4669344 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=10000 kind=shared seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469837160811 uptime_in_seconds:126 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084941 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 10000, + "kind": "shared", + "repeat": 3, + "measurements": [ + { + "commit_ms": 39.643, + "commit_to_ready_ms": 110.151, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 34537472, + "n": 10000, + "operation": "initial_load", + "ready_ms": 149.795, + "received_bytes": 1108058, + "redis_bytes": 4636928, + "search_p50_ns": 459, + "search_p95_ns": 2500, + "search_p99_ns": 6042, + "search_samples": 136, + "sent_bytes": 5147092 + }, + { + "commit_ms": 70.323, + "commit_to_ready_ms": 0.015, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35422208, + "n": 10000, + "operation": "identical_replace", + "ready_ms": 70.339, + "received_bytes": 929043, + "redis_bytes": 4005312, + "search_p50_ns": 1542, + "search_p95_ns": 2333, + "search_p99_ns": 2958, + "search_samples": 62, + "sent_bytes": 625471 + }, + { + "commit_ms": 5.287, + "commit_to_ready_ms": 20.024, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 35471360, + "n": 10000, + "operation": "add_1_repeat_0", + "ready_ms": 25.312, + "received_bytes": 1291786, + "redis_bytes": 5296976, + "search_p50_ns": 1833, + "search_p95_ns": 6958, + "search_p99_ns": 6958, + "search_samples": 20, + "sent_bytes": 650741 + }, + { + "commit_ms": 5.047, + "commit_to_ready_ms": 30.138, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36208640, + "n": 10000, + "operation": "remove_1_repeat_0", + "ready_ms": 35.185, + "received_bytes": 1291786, + "redis_bytes": 5938944, + "search_p50_ns": 5959, + "search_p95_ns": 7875, + "search_p99_ns": 8167, + "search_samples": 32, + "sent_bytes": 650723 + }, + { + "commit_ms": 4.987, + "commit_to_ready_ms": 30.193, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36306944, + "n": 10000, + "operation": "add_1_repeat_1", + "ready_ms": 35.18, + "received_bytes": 1291734, + "redis_bytes": 6595760, + "search_p50_ns": 6083, + "search_p95_ns": 7500, + "search_p99_ns": 7667, + "search_samples": 31, + "sent_bytes": 650715 + }, + { + "commit_ms": 5.064, + "commit_to_ready_ms": 30.126, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36356096, + "n": 10000, + "operation": "remove_1_repeat_1", + "ready_ms": 35.19, + "received_bytes": 1291735, + "redis_bytes": 7238720, + "search_p50_ns": 2500, + "search_p95_ns": 7541, + "search_p99_ns": 11583, + "search_samples": 32, + "sent_bytes": 650697 + }, + { + "commit_ms": 5.135, + "commit_to_ready_ms": 20.065, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36388864, + "n": 10000, + "operation": "add_1_repeat_2", + "ready_ms": 25.2, + "received_bytes": 1291684, + "redis_bytes": 7895488, + "search_p50_ns": 2291, + "search_p95_ns": 12542, + "search_p99_ns": 12542, + "search_samples": 20, + "sent_bytes": 650690 + }, + { + "commit_ms": 5.079, + "commit_to_ready_ms": 30.088, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36388864, + "n": 10000, + "operation": "remove_1_repeat_2", + "ready_ms": 35.168, + "received_bytes": 1291685, + "redis_bytes": 8551776, + "search_p50_ns": 3375, + "search_p95_ns": 7084, + "search_p99_ns": 7292, + "search_samples": 28, + "sent_bytes": 650672 + }, + { + "commit_ms": 6.303, + "commit_to_ready_ms": 30.085, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36405248, + "n": 10000, + "operation": "add_1", + "ready_ms": 36.389, + "received_bytes": 1291636, + "redis_bytes": 9208624, + "search_p50_ns": 2209, + "search_p95_ns": 7583, + "search_p99_ns": 7583, + "search_samples": 33, + "sent_bytes": 650667 + }, + { + "commit_ms": 7.295, + "commit_to_ready_ms": 20.092, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36454400, + "n": 10000, + "operation": "remove_1", + "ready_ms": 27.387, + "received_bytes": 1291639, + "redis_bytes": 9864848, + "search_p50_ns": 2583, + "search_p95_ns": 7000, + "search_p99_ns": 7833, + "search_samples": 22, + "sent_bytes": 650649 + }, + { + "commit_ms": 44.74, + "commit_to_ready_ms": 50.144, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36536320, + "n": 10000, + "operation": "add_1000", + "ready_ms": 94.884, + "received_bytes": 1453165, + "redis_bytes": 10984016, + "search_p50_ns": 1458, + "search_p95_ns": 6500, + "search_p99_ns": 7459, + "search_samples": 90, + "sent_bytes": 1881384 + }, + { + "commit_ms": 27.107, + "commit_to_ready_ms": 40.042, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36569088, + "n": 10000, + "operation": "remove_1000", + "ready_ms": 67.15, + "received_bytes": 1452828, + "redis_bytes": 11636432, + "search_p50_ns": 1667, + "search_p95_ns": 5666, + "search_p99_ns": 7417, + "search_samples": 54, + "sent_bytes": 1764101 + }, + { + "commit_ms": 7.5, + "commit_to_ready_ms": 20.083, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36585472, + "n": 10000, + "operation": "add_100", + "ready_ms": 27.584, + "received_bytes": 1309866, + "redis_bytes": 12335024, + "search_p50_ns": 2292, + "search_p95_ns": 6375, + "search_p99_ns": 6583, + "search_samples": 22, + "sent_bytes": 787796 + }, + { + "commit_ms": 7.348, + "commit_to_ready_ms": 30.056, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 36913152, + "n": 10000, + "operation": "remove_100", + "ready_ms": 37.405, + "received_bytes": 1309834, + "redis_bytes": 12991040, + "search_p50_ns": 2209, + "search_p95_ns": 7291, + "search_p99_ns": 7458, + "search_samples": 35, + "sent_bytes": 776828 + }, + { + "commit_ms": 103.714, + "commit_to_ready_ms": 100.116, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 39501824, + "n": 10000, + "operation": "full_replace", + "ready_ms": 203.831, + "received_bytes": 1886294, + "redis_bytes": 15324688, + "search_p50_ns": 1542, + "search_p95_ns": 6416, + "search_p99_ns": 6917, + "search_samples": 185, + "sent_bytes": 5768860 + } + ], + "startup_ms": 70.713, + "prune": { + "ms": 13.296, + "generations": 14, + "chunks": 4739, + "redis_bytes": 4694000 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=10000 kind=shared seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469903489870 uptime_in_seconds:192 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11085007 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 100000, + "kind": "diverse", + "repeat": 1, + "measurements": [ + { + "commit_ms": 65.19, + "commit_to_ready_ms": 180.057, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 125403136, + "n": 100000, + "operation": "initial_load", + "ready_ms": 245.248, + "received_bytes": 2514736, + "redis_bytes": 5642656, + "search_p50_ns": 458, + "search_p95_ns": 3917, + "search_p99_ns": 10833, + "search_samples": 233, + "sent_bytes": 6947556 + }, + { + "commit_ms": 123.224, + "commit_to_ready_ms": 0.017, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 141410304, + "n": 100000, + "operation": "identical_replace", + "ready_ms": 123.241, + "received_bytes": 2333782, + "redis_bytes": 5644144, + "search_p50_ns": 1708, + "search_p95_ns": 2958, + "search_p99_ns": 12333, + "search_samples": 96, + "sent_bytes": 683592 + }, + { + "commit_ms": 5.019, + "commit_to_ready_ms": 90.123, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 195280896, + "n": 100000, + "operation": "add_1_repeat_0", + "ready_ms": 95.143, + "received_bytes": 1390641, + "redis_bytes": 7101008, + "search_p50_ns": 2000, + "search_p95_ns": 10542, + "search_p99_ns": 26458, + "search_samples": 86, + "sent_bytes": 700245 + }, + { + "commit_ms": 4.948, + "commit_to_ready_ms": 70.172, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 221937664, + "n": 100000, + "operation": "remove_1_repeat_0", + "ready_ms": 75.121, + "received_bytes": 1390575, + "redis_bytes": 7806480, + "search_p50_ns": 2042, + "search_p95_ns": 6958, + "search_p99_ns": 11458, + "search_samples": 70, + "sent_bytes": 700126 + }, + { + "commit_ms": 6.592, + "commit_to_ready_ms": 80.117, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 222085120, + "n": 100000, + "operation": "add_1_repeat_1", + "ready_ms": 86.71, + "received_bytes": 1390830, + "redis_bytes": 8515024, + "search_p50_ns": 2125, + "search_p95_ns": 9667, + "search_p99_ns": 18375, + "search_samples": 69, + "sent_bytes": 700272 + }, + { + "commit_ms": 8.605, + "commit_to_ready_ms": 70.16, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 230326272, + "n": 100000, + "operation": "remove_1_repeat_1", + "ready_ms": 78.765, + "received_bytes": 1390832, + "redis_bytes": 9220448, + "search_p50_ns": 2000, + "search_p95_ns": 7916, + "search_p99_ns": 29083, + "search_samples": 73, + "sent_bytes": 700254 + }, + { + "commit_ms": 8.744, + "commit_to_ready_ms": 70.204, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 244514816, + "n": 100000, + "operation": "add_1_repeat_2", + "ready_ms": 78.948, + "received_bytes": 1390095, + "redis_bytes": 9926512, + "search_p50_ns": 1958, + "search_p95_ns": 7458, + "search_p99_ns": 11125, + "search_samples": 73, + "sent_bytes": 699904 + }, + { + "commit_ms": 8.663, + "commit_to_ready_ms": 80.164, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 244531200, + "n": 100000, + "operation": "remove_1_repeat_2", + "ready_ms": 88.827, + "received_bytes": 1390096, + "redis_bytes": 10631968, + "search_p50_ns": 2000, + "search_p95_ns": 8542, + "search_p99_ns": 11959, + "search_samples": 83, + "sent_bytes": 699886 + }, + { + "commit_ms": 8.703, + "commit_to_ready_ms": 70.188, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 244531200, + "n": 100000, + "operation": "add_1", + "ready_ms": 78.891, + "received_bytes": 1390516, + "redis_bytes": 11338336, + "search_p50_ns": 1792, + "search_p95_ns": 8292, + "search_p99_ns": 18083, + "search_samples": 58, + "sent_bytes": 700114 + }, + { + "commit_ms": 7.151, + "commit_to_ready_ms": 70.1, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 244563968, + "n": 100000, + "operation": "remove_1", + "ready_ms": 77.252, + "received_bytes": 1390519, + "redis_bytes": 12043760, + "search_p50_ns": 1959, + "search_p95_ns": 10834, + "search_p99_ns": 13875, + "search_samples": 68, + "sent_bytes": 700096 + }, + { + "commit_ms": 50.021, + "commit_to_ready_ms": 110.146, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 244580352, + "n": 100000, + "operation": "add_1000", + "ready_ms": 160.167, + "received_bytes": 2123281, + "redis_bytes": 13438544, + "search_p50_ns": 1916, + "search_p95_ns": 8791, + "search_p99_ns": 13959, + "search_samples": 149, + "sent_bytes": 2224930 + }, + { + "commit_ms": 42.349, + "commit_to_ready_ms": 110.07, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 244580352, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 152.419, + "received_bytes": 2123286, + "redis_bytes": 14119936, + "search_p50_ns": 2000, + "search_p95_ns": 8208, + "search_p99_ns": 22584, + "search_samples": 134, + "sent_bytes": 2201930 + }, + { + "commit_ms": 42.542, + "commit_to_ready_ms": 110.096, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 260145152, + "n": 100000, + "operation": "add_1000", + "ready_ms": 152.638, + "received_bytes": 2123286, + "redis_bytes": 14812288, + "search_p50_ns": 1958, + "search_p95_ns": 7916, + "search_p99_ns": 14458, + "search_samples": 130, + "sent_bytes": 2224930 + }, + { + "commit_ms": 43.662, + "commit_to_ready_ms": 110.13, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 260145152, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 153.793, + "received_bytes": 2123286, + "redis_bytes": 15498240, + "search_p50_ns": 1959, + "search_p95_ns": 8167, + "search_p99_ns": 17708, + "search_samples": 136, + "sent_bytes": 2201930 + }, + { + "commit_ms": 177.639, + "commit_to_ready_ms": 190.102, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 276070400, + "n": 100000, + "operation": "full_replace", + "ready_ms": 367.741, + "received_bytes": 4880067, + "redis_bytes": 19047744, + "search_p50_ns": 1709, + "search_p95_ns": 5042, + "search_p99_ns": 9667, + "search_samples": 337, + "sent_bytes": 7827759 + } + ], + "startup_ms": 152.635, + "prune": { + "ms": 13.61, + "generations": 14, + "chunks": 4990, + "redis_bytes": 5838032 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=100000 kind=diverse seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469775495609 uptime_in_seconds:64 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084879 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 100000, + "kind": "diverse", + "repeat": 2, + "measurements": [ + { + "commit_ms": 66.926, + "commit_to_ready_ms": 180.129, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 126402560, + "n": 100000, + "operation": "initial_load", + "ready_ms": 247.055, + "received_bytes": 2514753, + "redis_bytes": 5642304, + "search_p50_ns": 416, + "search_p95_ns": 2709, + "search_p99_ns": 11542, + "search_samples": 244, + "sent_bytes": 6947556 + }, + { + "commit_ms": 106.911, + "commit_to_ready_ms": 0.012, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 146227200, + "n": 100000, + "operation": "identical_replace", + "ready_ms": 106.924, + "received_bytes": 2333799, + "redis_bytes": 5659152, + "search_p50_ns": 1333, + "search_p95_ns": 2416, + "search_p99_ns": 11500, + "search_samples": 89, + "sent_bytes": 683592 + }, + { + "commit_ms": 5.167, + "commit_to_ready_ms": 90.042, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 216465408, + "n": 100000, + "operation": "add_1_repeat_0", + "ready_ms": 95.21, + "received_bytes": 1390586, + "redis_bytes": 7102736, + "search_p50_ns": 1792, + "search_p95_ns": 8875, + "search_p99_ns": 21417, + "search_samples": 91, + "sent_bytes": 700144 + }, + { + "commit_ms": 5.229, + "commit_to_ready_ms": 80.049, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 220921856, + "n": 100000, + "operation": "remove_1_repeat_0", + "ready_ms": 85.278, + "received_bytes": 1390592, + "redis_bytes": 7808176, + "search_p50_ns": 2000, + "search_p95_ns": 14250, + "search_p99_ns": 29041, + "search_samples": 79, + "sent_bytes": 700126 + }, + { + "commit_ms": 6.479, + "commit_to_ready_ms": 80.083, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 220954624, + "n": 100000, + "operation": "add_1_repeat_1", + "ready_ms": 86.562, + "received_bytes": 1390847, + "redis_bytes": 8514656, + "search_p50_ns": 1917, + "search_p95_ns": 9625, + "search_p99_ns": 36291, + "search_samples": 64, + "sent_bytes": 700272 + }, + { + "commit_ms": 8.89, + "commit_to_ready_ms": 90.186, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 220971008, + "n": 100000, + "operation": "remove_1_repeat_1", + "ready_ms": 99.076, + "received_bytes": 1390848, + "redis_bytes": 9220112, + "search_p50_ns": 2000, + "search_p95_ns": 9959, + "search_p99_ns": 16792, + "search_samples": 94, + "sent_bytes": 700254 + }, + { + "commit_ms": 7.964, + "commit_to_ready_ms": 80.183, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 234110976, + "n": 100000, + "operation": "add_1_repeat_2", + "ready_ms": 88.148, + "received_bytes": 1390111, + "redis_bytes": 9926224, + "search_p50_ns": 1917, + "search_p95_ns": 4625, + "search_p99_ns": 17875, + "search_samples": 64, + "sent_bytes": 699904 + }, + { + "commit_ms": 8.188, + "commit_to_ready_ms": 80.074, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 242122752, + "n": 100000, + "operation": "remove_1_repeat_2", + "ready_ms": 88.263, + "received_bytes": 1390112, + "redis_bytes": 10631648, + "search_p50_ns": 2041, + "search_p95_ns": 13583, + "search_p99_ns": 25583, + "search_samples": 82, + "sent_bytes": 699886 + }, + { + "commit_ms": 8.999, + "commit_to_ready_ms": 100.189, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 256327680, + "n": 100000, + "operation": "add_1", + "ready_ms": 109.188, + "received_bytes": 1390531, + "redis_bytes": 11338064, + "search_p50_ns": 4750, + "search_p95_ns": 16792, + "search_p99_ns": 25750, + "search_samples": 85, + "sent_bytes": 700114 + }, + { + "commit_ms": 6.821, + "commit_to_ready_ms": 90.167, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 256344064, + "n": 100000, + "operation": "remove_1", + "ready_ms": 96.988, + "received_bytes": 1390535, + "redis_bytes": 12043504, + "search_p50_ns": 3375, + "search_p95_ns": 16917, + "search_p99_ns": 23583, + "search_samples": 89, + "sent_bytes": 700096 + }, + { + "commit_ms": 56.7, + "commit_to_ready_ms": 120.116, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 256360448, + "n": 100000, + "operation": "add_1000", + "ready_ms": 176.816, + "received_bytes": 2123299, + "redis_bytes": 13438736, + "search_p50_ns": 1625, + "search_p95_ns": 8250, + "search_p99_ns": 14750, + "search_samples": 152, + "sent_bytes": 2224930 + }, + { + "commit_ms": 40.991, + "commit_to_ready_ms": 100.186, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 256393216, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 141.178, + "received_bytes": 2123230, + "redis_bytes": 14139536, + "search_p50_ns": 1583, + "search_p95_ns": 5333, + "search_p99_ns": 21708, + "search_samples": 123, + "sent_bytes": 2201829 + }, + { + "commit_ms": 36.632, + "commit_to_ready_ms": 120.089, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 260276224, + "n": 100000, + "operation": "add_1000", + "ready_ms": 156.722, + "received_bytes": 2123230, + "redis_bytes": 14810272, + "search_p50_ns": 1833, + "search_p95_ns": 8375, + "search_p99_ns": 17209, + "search_samples": 136, + "sent_bytes": 2224829 + }, + { + "commit_ms": 41.552, + "commit_to_ready_ms": 110.103, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 260276224, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 151.656, + "received_bytes": 2123230, + "redis_bytes": 15515712, + "search_p50_ns": 1709, + "search_p95_ns": 6583, + "search_p99_ns": 16458, + "search_samples": 129, + "sent_bytes": 2201829 + }, + { + "commit_ms": 169.514, + "commit_to_ready_ms": 210.103, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 274825216, + "n": 100000, + "operation": "full_replace", + "ready_ms": 379.618, + "received_bytes": 4880009, + "redis_bytes": 19044576, + "search_p50_ns": 1833, + "search_p95_ns": 9917, + "search_p99_ns": 13250, + "search_samples": 353, + "sent_bytes": 7827658 + } + ], + "startup_ms": 139.223, + "prune": { + "ms": 26.89, + "generations": 14, + "chunks": 4990, + "redis_bytes": 5838240 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=100000 kind=diverse seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469842349992 uptime_in_seconds:131 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084946 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 100000, + "kind": "diverse", + "repeat": 3, + "measurements": [ + { + "commit_ms": 66.757, + "commit_to_ready_ms": 180.14, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 121552896, + "n": 100000, + "operation": "initial_load", + "ready_ms": 246.898, + "received_bytes": 2514759, + "redis_bytes": 5650480, + "search_p50_ns": 458, + "search_p95_ns": 6500, + "search_p99_ns": 15459, + "search_samples": 233, + "sent_bytes": 6947556 + }, + { + "commit_ms": 123.36, + "commit_to_ready_ms": 0.019, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 123092992, + "n": 100000, + "operation": "identical_replace", + "ready_ms": 123.38, + "received_bytes": 2333877, + "redis_bytes": 5651984, + "search_p50_ns": 1708, + "search_p95_ns": 2666, + "search_p99_ns": 4667, + "search_samples": 111, + "sent_bytes": 683693 + }, + { + "commit_ms": 5.147, + "commit_to_ready_ms": 90.045, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 201326592, + "n": 100000, + "operation": "add_1_repeat_0", + "ready_ms": 95.192, + "received_bytes": 1390592, + "redis_bytes": 7109872, + "search_p50_ns": 1958, + "search_p95_ns": 9250, + "search_p99_ns": 21708, + "search_samples": 92, + "sent_bytes": 700144 + }, + { + "commit_ms": 5.224, + "commit_to_ready_ms": 70.061, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 234946560, + "n": 100000, + "operation": "remove_1_repeat_0", + "ready_ms": 75.286, + "received_bytes": 1390598, + "redis_bytes": 7815328, + "search_p50_ns": 1917, + "search_p95_ns": 5875, + "search_p99_ns": 12292, + "search_samples": 73, + "sent_bytes": 700126 + }, + { + "commit_ms": 6.555, + "commit_to_ready_ms": 80.128, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 234946560, + "n": 100000, + "operation": "add_1_repeat_1", + "ready_ms": 86.683, + "received_bytes": 1390853, + "redis_bytes": 8521888, + "search_p50_ns": 1875, + "search_p95_ns": 8250, + "search_p99_ns": 14125, + "search_samples": 70, + "sent_bytes": 700272 + }, + { + "commit_ms": 8.61, + "commit_to_ready_ms": 70.169, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 249184256, + "n": 100000, + "operation": "remove_1_repeat_1", + "ready_ms": 78.78, + "received_bytes": 1390854, + "redis_bytes": 9227296, + "search_p50_ns": 2042, + "search_p95_ns": 7291, + "search_p99_ns": 8250, + "search_samples": 73, + "sent_bytes": 700254 + }, + { + "commit_ms": 8.837, + "commit_to_ready_ms": 80.224, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 249184256, + "n": 100000, + "operation": "add_1_repeat_2", + "ready_ms": 89.061, + "received_bytes": 1390117, + "redis_bytes": 9933376, + "search_p50_ns": 2000, + "search_p95_ns": 9541, + "search_p99_ns": 25375, + "search_samples": 85, + "sent_bytes": 699904 + }, + { + "commit_ms": 9.064, + "commit_to_ready_ms": 70.114, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 249184256, + "n": 100000, + "operation": "remove_1_repeat_2", + "ready_ms": 79.178, + "received_bytes": 1390118, + "redis_bytes": 10638832, + "search_p50_ns": 1917, + "search_p95_ns": 18834, + "search_p99_ns": 20875, + "search_samples": 60, + "sent_bytes": 699886 + }, + { + "commit_ms": 8.776, + "commit_to_ready_ms": 80.202, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 249217024, + "n": 100000, + "operation": "add_1", + "ready_ms": 88.978, + "received_bytes": 1390534, + "redis_bytes": 11345232, + "search_p50_ns": 2000, + "search_p95_ns": 9291, + "search_p99_ns": 51916, + "search_samples": 71, + "sent_bytes": 700114 + }, + { + "commit_ms": 7.246, + "commit_to_ready_ms": 70.113, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 249217024, + "n": 100000, + "operation": "remove_1", + "ready_ms": 77.359, + "received_bytes": 1390541, + "redis_bytes": 12050672, + "search_p50_ns": 1916, + "search_p95_ns": 13792, + "search_p99_ns": 49375, + "search_samples": 59, + "sent_bytes": 700096 + }, + { + "commit_ms": 51.153, + "commit_to_ready_ms": 110.055, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 249233408, + "n": 100000, + "operation": "add_1000", + "ready_ms": 161.209, + "received_bytes": 2123306, + "redis_bytes": 13426496, + "search_p50_ns": 1791, + "search_p95_ns": 7834, + "search_p99_ns": 21000, + "search_samples": 155, + "sent_bytes": 2224930 + }, + { + "commit_ms": 44.189, + "commit_to_ready_ms": 100.042, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 249266176, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 144.232, + "received_bytes": 2123236, + "redis_bytes": 14148080, + "search_p50_ns": 1833, + "search_p95_ns": 7000, + "search_p99_ns": 9250, + "search_samples": 124, + "sent_bytes": 2201829 + }, + { + "commit_ms": 39.142, + "commit_to_ready_ms": 110.054, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 249282560, + "n": 100000, + "operation": "add_1000", + "ready_ms": 149.197, + "received_bytes": 2123236, + "redis_bytes": 14820864, + "search_p50_ns": 1917, + "search_p95_ns": 7625, + "search_p99_ns": 16750, + "search_samples": 131, + "sent_bytes": 2224829 + }, + { + "commit_ms": 43.405, + "commit_to_ready_ms": 110.06, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 249282560, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 153.465, + "received_bytes": 2123308, + "redis_bytes": 15526320, + "search_p50_ns": 1833, + "search_p95_ns": 7958, + "search_p99_ns": 10292, + "search_samples": 136, + "sent_bytes": 2201930 + }, + { + "commit_ms": 178.989, + "commit_to_ready_ms": 190.192, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 275087360, + "n": 100000, + "operation": "full_replace", + "ready_ms": 369.182, + "received_bytes": 4880088, + "redis_bytes": 19740464, + "search_p50_ns": 1750, + "search_p95_ns": 6917, + "search_p99_ns": 16917, + "search_samples": 338, + "sent_bytes": 7827759 + } + ], + "startup_ms": 152.651, + "prune": { + "ms": 13.879, + "generations": 14, + "chunks": 4990, + "redis_bytes": 5850352 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=100000 kind=diverse seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469908510306 uptime_in_seconds:197 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11085012 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 100000, + "kind": "korean", + "repeat": 1, + "measurements": [ + { + "commit_ms": 88.333, + "commit_to_ready_ms": 220.071, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 213516288, + "n": 100000, + "operation": "initial_load", + "ready_ms": 308.405, + "received_bytes": 4515775, + "redis_bytes": 7807824, + "search_p50_ns": 708, + "search_p95_ns": 4417, + "search_p99_ns": 18000, + "search_samples": 301, + "sent_bytes": 8948593 + }, + { + "commit_ms": 146.792, + "commit_to_ready_ms": 0.018, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 230457344, + "n": 100000, + "operation": "identical_replace", + "ready_ms": 146.811, + "received_bytes": 4334893, + "redis_bytes": 7812400, + "search_p50_ns": 2084, + "search_p95_ns": 3167, + "search_p99_ns": 8500, + "search_samples": 124, + "sent_bytes": 683693 + }, + { + "commit_ms": 5.099, + "commit_to_ready_ms": 110.064, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 364249088, + "n": 100000, + "operation": "add_1_repeat_0", + "ready_ms": 115.163, + "received_bytes": 1390831, + "redis_bytes": 9269376, + "search_p50_ns": 2625, + "search_p95_ns": 10500, + "search_p99_ns": 22625, + "search_samples": 111, + "sent_bytes": 700274 + }, + { + "commit_ms": 4.836, + "commit_to_ready_ms": 100.13, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 407699456, + "n": 100000, + "operation": "remove_1_repeat_0", + "ready_ms": 104.967, + "received_bytes": 1390837, + "redis_bytes": 9976864, + "search_p50_ns": 2792, + "search_p95_ns": 9625, + "search_p99_ns": 27333, + "search_samples": 100, + "sent_bytes": 700256 + }, + { + "commit_ms": 7.622, + "commit_to_ready_ms": 100.17, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 412762112, + "n": 100000, + "operation": "add_1_repeat_1", + "ready_ms": 107.793, + "received_bytes": 1391702, + "redis_bytes": 10683936, + "search_p50_ns": 2583, + "search_p95_ns": 12750, + "search_p99_ns": 22000, + "search_samples": 101, + "sent_bytes": 700707 + }, + { + "commit_ms": 9.031, + "commit_to_ready_ms": 90.131, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 413319168, + "n": 100000, + "operation": "remove_1_repeat_1", + "ready_ms": 99.163, + "received_bytes": 1391706, + "redis_bytes": 11389360, + "search_p50_ns": 2750, + "search_p95_ns": 13542, + "search_p99_ns": 35166, + "search_samples": 88, + "sent_bytes": 700689 + }, + { + "commit_ms": 8.763, + "commit_to_ready_ms": 110.195, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 413319168, + "n": 100000, + "operation": "add_1_repeat_2", + "ready_ms": 118.958, + "received_bytes": 1391705, + "redis_bytes": 12096352, + "search_p50_ns": 2500, + "search_p95_ns": 10084, + "search_p99_ns": 18667, + "search_samples": 113, + "sent_bytes": 700707 + }, + { + "commit_ms": 8.814, + "commit_to_ready_ms": 90.186, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 413319168, + "n": 100000, + "operation": "remove_1_repeat_2", + "ready_ms": 99, + "received_bytes": 1391706, + "redis_bytes": 12801824, + "search_p50_ns": 2708, + "search_p95_ns": 9834, + "search_p99_ns": 24333, + "search_samples": 87, + "sent_bytes": 700689 + }, + { + "commit_ms": 7.606, + "commit_to_ready_ms": 100.159, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 413319168, + "n": 100000, + "operation": "add_1", + "ready_ms": 107.766, + "received_bytes": 1391708, + "redis_bytes": 13509008, + "search_p50_ns": 2583, + "search_p95_ns": 10375, + "search_p99_ns": 28958, + "search_samples": 103, + "sent_bytes": 700709 + }, + { + "commit_ms": 8.55, + "commit_to_ready_ms": 100.156, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 413335552, + "n": 100000, + "operation": "remove_1", + "ready_ms": 108.707, + "received_bytes": 1391712, + "redis_bytes": 14214416, + "search_p50_ns": 2791, + "search_p95_ns": 10250, + "search_p99_ns": 21708, + "search_samples": 104, + "sent_bytes": 700691 + }, + { + "commit_ms": 54.434, + "commit_to_ready_ms": 140.081, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 413335552, + "n": 100000, + "operation": "add_1000", + "ready_ms": 194.515, + "received_bytes": 2998132, + "redis_bytes": 15410656, + "search_p50_ns": 2417, + "search_p95_ns": 10166, + "search_p99_ns": 23625, + "search_samples": 178, + "sent_bytes": 2662356 + }, + { + "commit_ms": 49.341, + "commit_to_ready_ms": 120.061, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 413335552, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 169.403, + "received_bytes": 2998058, + "redis_bytes": 16796016, + "search_p50_ns": 2375, + "search_p95_ns": 9250, + "search_p99_ns": 22375, + "search_samples": 162, + "sent_bytes": 2639248 + }, + { + "commit_ms": 45.749, + "commit_to_ready_ms": 140.133, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 413351936, + "n": 100000, + "operation": "add_1000", + "ready_ms": 185.883, + "received_bytes": 2998132, + "redis_bytes": 17466320, + "search_p50_ns": 2375, + "search_p95_ns": 9584, + "search_p99_ns": 13666, + "search_samples": 178, + "sent_bytes": 2662356 + }, + { + "commit_ms": 46.796, + "commit_to_ready_ms": 120.156, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 423084032, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 166.952, + "received_bytes": 2998059, + "redis_bytes": 18171808, + "search_p50_ns": 2458, + "search_p95_ns": 8250, + "search_p99_ns": 16500, + "search_samples": 157, + "sent_bytes": 2639248 + }, + { + "commit_ms": 210.799, + "commit_to_ready_ms": 240.132, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 521977856, + "n": 100000, + "operation": "full_replace", + "ready_ms": 450.932, + "received_bytes": 8882464, + "redis_bytes": 23907824, + "search_p50_ns": 2209, + "search_p95_ns": 7083, + "search_p99_ns": 9791, + "search_samples": 418, + "sent_bytes": 9829119 + } + ], + "startup_ms": 194.578, + "prune": { + "ms": 14.225, + "generations": 14, + "chunks": 4990, + "redis_bytes": 8046736 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=100000 kind=korean seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469777803212 uptime_in_seconds:66 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084881 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 100000, + "kind": "korean", + "repeat": 2, + "measurements": [ + { + "commit_ms": 156.091, + "commit_to_ready_ms": 470.07, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 210042880, + "n": 100000, + "operation": "initial_load", + "ready_ms": 626.161, + "received_bytes": 4515864, + "redis_bytes": 7806736, + "search_p50_ns": 1625, + "search_p95_ns": 6333, + "search_p99_ns": 12708, + "search_samples": 613, + "sent_bytes": 8948694 + }, + { + "commit_ms": 380.08, + "commit_to_ready_ms": 0.051, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 212156416, + "n": 100000, + "operation": "identical_replace", + "ready_ms": 380.132, + "received_bytes": 4335270, + "redis_bytes": 7809776, + "search_p50_ns": 9625, + "search_p95_ns": 28208, + "search_p99_ns": 82875, + "search_samples": 258, + "sent_bytes": 684198 + }, + { + "commit_ms": 49.716, + "commit_to_ready_ms": 240.22, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 297205760, + "n": 100000, + "operation": "add_1_repeat_0", + "ready_ms": 289.936, + "received_bytes": 1390991, + "redis_bytes": 8585184, + "search_p50_ns": 5417, + "search_p95_ns": 18875, + "search_p99_ns": 77166, + "search_samples": 236, + "sent_bytes": 700476 + }, + { + "commit_ms": 8.401, + "commit_to_ready_ms": 120.097, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 390840320, + "n": 100000, + "operation": "remove_1_repeat_0", + "ready_ms": 128.498, + "received_bytes": 1390852, + "redis_bytes": 9974672, + "search_p50_ns": 3416, + "search_p95_ns": 11709, + "search_p99_ns": 18042, + "search_samples": 115, + "sent_bytes": 700256 + }, + { + "commit_ms": 9.339, + "commit_to_ready_ms": 110.096, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 396492800, + "n": 100000, + "operation": "add_1_repeat_1", + "ready_ms": 119.435, + "received_bytes": 1391716, + "redis_bytes": 10681744, + "search_p50_ns": 2666, + "search_p95_ns": 12833, + "search_p99_ns": 19708, + "search_samples": 104, + "sent_bytes": 700707 + }, + { + "commit_ms": 8.661, + "commit_to_ready_ms": 100.168, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 414449664, + "n": 100000, + "operation": "remove_1_repeat_1", + "ready_ms": 108.829, + "received_bytes": 1391717, + "redis_bytes": 11387200, + "search_p50_ns": 2625, + "search_p95_ns": 10417, + "search_p99_ns": 25500, + "search_samples": 95, + "sent_bytes": 700689 + }, + { + "commit_ms": 8.999, + "commit_to_ready_ms": 110.158, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 414466048, + "n": 100000, + "operation": "add_1_repeat_2", + "ready_ms": 119.157, + "received_bytes": 1391719, + "redis_bytes": 12094256, + "search_p50_ns": 2916, + "search_p95_ns": 12458, + "search_p99_ns": 14458, + "search_samples": 114, + "sent_bytes": 700707 + }, + { + "commit_ms": 7.62, + "commit_to_ready_ms": 100.123, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 414466048, + "n": 100000, + "operation": "remove_1_repeat_2", + "ready_ms": 107.744, + "received_bytes": 1391720, + "redis_bytes": 12799760, + "search_p50_ns": 2792, + "search_p95_ns": 9833, + "search_p99_ns": 24250, + "search_samples": 94, + "sent_bytes": 700689 + }, + { + "commit_ms": 7.708, + "commit_to_ready_ms": 100.191, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 414515200, + "n": 100000, + "operation": "add_1", + "ready_ms": 107.899, + "received_bytes": 1391721, + "redis_bytes": 13506928, + "search_p50_ns": 2833, + "search_p95_ns": 13958, + "search_p99_ns": 216375, + "search_samples": 92, + "sent_bytes": 700709 + }, + { + "commit_ms": 8.711, + "commit_to_ready_ms": 110.184, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 414531584, + "n": 100000, + "operation": "remove_1", + "ready_ms": 118.896, + "received_bytes": 1391725, + "redis_bytes": 14212288, + "search_p50_ns": 2625, + "search_p95_ns": 11666, + "search_p99_ns": 27334, + "search_samples": 106, + "sent_bytes": 700691 + }, + { + "commit_ms": 55.377, + "commit_to_ready_ms": 140.07, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 414629888, + "n": 100000, + "operation": "add_1000", + "ready_ms": 195.448, + "received_bytes": 2998146, + "redis_bytes": 16092656, + "search_p50_ns": 2000, + "search_p95_ns": 5250, + "search_p99_ns": 14375, + "search_samples": 182, + "sent_bytes": 2662356 + }, + { + "commit_ms": 53.997, + "commit_to_ready_ms": 140.141, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 414695424, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 194.139, + "received_bytes": 2998147, + "redis_bytes": 16793984, + "search_p50_ns": 2084, + "search_p95_ns": 6625, + "search_p99_ns": 17541, + "search_samples": 182, + "sent_bytes": 2639349 + }, + { + "commit_ms": 49.676, + "commit_to_ready_ms": 150.121, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 414695424, + "n": 100000, + "operation": "add_1000", + "ready_ms": 199.797, + "received_bytes": 2998148, + "redis_bytes": 16780256, + "search_p50_ns": 2083, + "search_p95_ns": 7458, + "search_p99_ns": 14917, + "search_samples": 186, + "sent_bytes": 2662356 + }, + { + "commit_ms": 54.744, + "commit_to_ready_ms": 150.129, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 414711808, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 204.874, + "received_bytes": 2998147, + "redis_bytes": 18169792, + "search_p50_ns": 2209, + "search_p95_ns": 15292, + "search_p99_ns": 35916, + "search_samples": 188, + "sent_bytes": 2639349 + }, + { + "commit_ms": 208.199, + "commit_to_ready_ms": 240.036, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 442089472, + "n": 100000, + "operation": "full_replace", + "ready_ms": 448.235, + "received_bytes": 8882480, + "redis_bytes": 23907040, + "search_p50_ns": 2000, + "search_p95_ns": 5542, + "search_p99_ns": 14791, + "search_samples": 438, + "sent_bytes": 9829119 + } + ], + "startup_ms": 290.078, + "prune": { + "ms": 14.887, + "generations": 14, + "chunks": 4990, + "redis_bytes": 8046016 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=100000 kind=korean seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469844733177 uptime_in_seconds:133 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084948 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 100000, + "kind": "korean", + "repeat": 3, + "measurements": [ + { + "commit_ms": 87.086, + "commit_to_ready_ms": 220.073, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 211386368, + "n": 100000, + "operation": "initial_load", + "ready_ms": 307.159, + "received_bytes": 4515798, + "redis_bytes": 7816128, + "search_p50_ns": 708, + "search_p95_ns": 2917, + "search_p99_ns": 11208, + "search_samples": 302, + "sent_bytes": 8948593 + }, + { + "commit_ms": 143.907, + "commit_to_ready_ms": 0.017, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 213483520, + "n": 100000, + "operation": "identical_replace", + "ready_ms": 143.925, + "received_bytes": 4334914, + "redis_bytes": 7836320, + "search_p50_ns": 2125, + "search_p95_ns": 2459, + "search_p99_ns": 4125, + "search_samples": 143, + "sent_bytes": 683693 + }, + { + "commit_ms": 5.007, + "commit_to_ready_ms": 110.133, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 311853056, + "n": 100000, + "operation": "add_1_repeat_0", + "ready_ms": 115.14, + "received_bytes": 1390852, + "redis_bytes": 9277696, + "search_p50_ns": 2459, + "search_p95_ns": 11917, + "search_p99_ns": 22708, + "search_samples": 108, + "sent_bytes": 700274 + }, + { + "commit_ms": 5.038, + "commit_to_ready_ms": 100.111, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 339591168, + "n": 100000, + "operation": "remove_1_repeat_0", + "ready_ms": 105.149, + "received_bytes": 1390858, + "redis_bytes": 9983120, + "search_p50_ns": 2708, + "search_p95_ns": 9750, + "search_p99_ns": 18667, + "search_samples": 100, + "sent_bytes": 700256 + }, + { + "commit_ms": 7.008, + "commit_to_ready_ms": 110.159, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 381911040, + "n": 100000, + "operation": "add_1_repeat_1", + "ready_ms": 117.167, + "received_bytes": 1391723, + "redis_bytes": 10690240, + "search_p50_ns": 2667, + "search_p95_ns": 9625, + "search_p99_ns": 25250, + "search_samples": 113, + "sent_bytes": 700707 + }, + { + "commit_ms": 9.097, + "commit_to_ready_ms": 90.08, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 381927424, + "n": 100000, + "operation": "remove_1_repeat_1", + "ready_ms": 99.177, + "received_bytes": 1391727, + "redis_bytes": 11395664, + "search_p50_ns": 2750, + "search_p95_ns": 9834, + "search_p99_ns": 35417, + "search_samples": 86, + "sent_bytes": 700689 + }, + { + "commit_ms": 8.789, + "commit_to_ready_ms": 110.18, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 381927424, + "n": 100000, + "operation": "add_1_repeat_2", + "ready_ms": 118.97, + "received_bytes": 1391726, + "redis_bytes": 12102672, + "search_p50_ns": 2666, + "search_p95_ns": 10125, + "search_p99_ns": 30667, + "search_samples": 114, + "sent_bytes": 700707 + }, + { + "commit_ms": 7.488, + "commit_to_ready_ms": 100.116, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 416661504, + "n": 100000, + "operation": "remove_1_repeat_2", + "ready_ms": 107.604, + "received_bytes": 1391727, + "redis_bytes": 12808144, + "search_p50_ns": 2584, + "search_p95_ns": 10584, + "search_p99_ns": 21542, + "search_samples": 102, + "sent_bytes": 700689 + }, + { + "commit_ms": 7.027, + "commit_to_ready_ms": 100.117, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 416710656, + "n": 100000, + "operation": "add_1", + "ready_ms": 107.145, + "received_bytes": 1391728, + "redis_bytes": 13515312, + "search_p50_ns": 2625, + "search_p95_ns": 10500, + "search_p99_ns": 15667, + "search_samples": 103, + "sent_bytes": 700709 + }, + { + "commit_ms": 8.346, + "commit_to_ready_ms": 100.126, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 416759808, + "n": 100000, + "operation": "remove_1", + "ready_ms": 108.472, + "received_bytes": 1391732, + "redis_bytes": 14220752, + "search_p50_ns": 2750, + "search_p95_ns": 10334, + "search_p99_ns": 23083, + "search_samples": 103, + "sent_bytes": 700691 + }, + { + "commit_ms": 56.1, + "commit_to_ready_ms": 140.075, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 416776192, + "n": 100000, + "operation": "add_1000", + "ready_ms": 196.175, + "received_bytes": 2998153, + "redis_bytes": 16101328, + "search_p50_ns": 2292, + "search_p95_ns": 9458, + "search_p99_ns": 14333, + "search_samples": 185, + "sent_bytes": 2662356 + }, + { + "commit_ms": 48.989, + "commit_to_ready_ms": 140.148, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 416776192, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 189.137, + "received_bytes": 2998153, + "redis_bytes": 16802576, + "search_p50_ns": 2458, + "search_p95_ns": 10083, + "search_p99_ns": 21625, + "search_samples": 184, + "sent_bytes": 2639349 + }, + { + "commit_ms": 49.006, + "commit_to_ready_ms": 120.167, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 416776192, + "n": 100000, + "operation": "add_1000", + "ready_ms": 169.174, + "received_bytes": 2998080, + "redis_bytes": 16788912, + "search_p50_ns": 2417, + "search_p95_ns": 10542, + "search_p99_ns": 18875, + "search_samples": 159, + "sent_bytes": 2662255 + }, + { + "commit_ms": 45.27, + "commit_to_ready_ms": 140.054, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 416808960, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 185.324, + "received_bytes": 2998151, + "redis_bytes": 18178480, + "search_p50_ns": 2458, + "search_p95_ns": 9125, + "search_p99_ns": 12042, + "search_samples": 179, + "sent_bytes": 2639349 + }, + { + "commit_ms": 215.762, + "commit_to_ready_ms": 230.131, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 426999808, + "n": 100000, + "operation": "full_replace", + "ready_ms": 445.893, + "received_bytes": 8882485, + "redis_bytes": 23917040, + "search_p50_ns": 2167, + "search_p95_ns": 6250, + "search_p99_ns": 12042, + "search_samples": 421, + "sent_bytes": 9829119 + } + ], + "startup_ms": 192.285, + "prune": { + "ms": 14.362, + "generations": 14, + "chunks": 4990, + "redis_bytes": 8054320 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=100000 kind=korean seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469910824260 uptime_in_seconds:199 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11085014 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 100000, + "kind": "shared", + "repeat": 1, + "measurements": [ + { + "commit_ms": 59.987, + "commit_to_ready_ms": 140.167, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 60735488, + "n": 100000, + "operation": "initial_load", + "ready_ms": 200.154, + "received_bytes": 3414436, + "redis_bytes": 7301488, + "search_p50_ns": 458, + "search_p95_ns": 2875, + "search_p99_ns": 33083, + "search_samples": 195, + "sent_bytes": 7847320 + }, + { + "commit_ms": 114.905, + "commit_to_ready_ms": 0.016, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 70778880, + "n": 100000, + "operation": "identical_replace", + "ready_ms": 114.921, + "received_bytes": 3233783, + "redis_bytes": 6622064, + "search_p50_ns": 1916, + "search_p95_ns": 2584, + "search_p99_ns": 12458, + "search_samples": 103, + "sent_bytes": 683592 + }, + { + "commit_ms": 5.022, + "commit_to_ready_ms": 40.128, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 85000192, + "n": 100000, + "operation": "add_1_repeat_0", + "ready_ms": 45.15, + "received_bytes": 1390650, + "redis_bytes": 8078048, + "search_p50_ns": 2125, + "search_p95_ns": 7583, + "search_p99_ns": 7833, + "search_samples": 40, + "sent_bytes": 700189 + }, + { + "commit_ms": 4.825, + "commit_to_ready_ms": 40.131, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 91553792, + "n": 100000, + "operation": "remove_1_repeat_0", + "ready_ms": 44.957, + "received_bytes": 1390655, + "redis_bytes": 8786080, + "search_p50_ns": 1958, + "search_p95_ns": 8416, + "search_p99_ns": 8458, + "search_samples": 36, + "sent_bytes": 700171 + }, + { + "commit_ms": 5.8, + "commit_to_ready_ms": 40.163, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96256000, + "n": 100000, + "operation": "add_1_repeat_1", + "ready_ms": 45.963, + "received_bytes": 1390655, + "redis_bytes": 9492512, + "search_p50_ns": 2833, + "search_p95_ns": 15834, + "search_p99_ns": 23833, + "search_samples": 34, + "sent_bytes": 700189 + }, + { + "commit_ms": 5.234, + "commit_to_ready_ms": 50.053, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96436224, + "n": 100000, + "operation": "remove_1_repeat_1", + "ready_ms": 55.287, + "received_bytes": 1390651, + "redis_bytes": 10197904, + "search_p50_ns": 2625, + "search_p95_ns": 10833, + "search_p99_ns": 20250, + "search_samples": 51, + "sent_bytes": 700171 + }, + { + "commit_ms": 7.058, + "commit_to_ready_ms": 40.069, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96436224, + "n": 100000, + "operation": "add_1_repeat_2", + "ready_ms": 47.127, + "received_bytes": 1390908, + "redis_bytes": 10904416, + "search_p50_ns": 2208, + "search_p95_ns": 8208, + "search_p99_ns": 8625, + "search_samples": 36, + "sent_bytes": 700314 + }, + { + "commit_ms": 7.531, + "commit_to_ready_ms": 40.146, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96632832, + "n": 100000, + "operation": "remove_1_repeat_2", + "ready_ms": 47.678, + "received_bytes": 1390908, + "redis_bytes": 11609872, + "search_p50_ns": 2542, + "search_p95_ns": 10958, + "search_p99_ns": 23750, + "search_samples": 34, + "sent_bytes": 700296 + }, + { + "commit_ms": 7.932, + "commit_to_ready_ms": 50.164, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96681984, + "n": 100000, + "operation": "add_1", + "ready_ms": 58.096, + "received_bytes": 1390761, + "redis_bytes": 12316384, + "search_p50_ns": 2000, + "search_p95_ns": 8375, + "search_p99_ns": 8500, + "search_samples": 52, + "sent_bytes": 700241 + }, + { + "commit_ms": 8.855, + "commit_to_ready_ms": 40.213, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96714752, + "n": 100000, + "operation": "remove_1", + "ready_ms": 49.068, + "received_bytes": 1390762, + "redis_bytes": 13021808, + "search_p50_ns": 1917, + "search_p95_ns": 7834, + "search_p99_ns": 21792, + "search_samples": 45, + "sent_bytes": 700223 + }, + { + "commit_ms": 52.677, + "commit_to_ready_ms": 60.123, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 100679680, + "n": 100000, + "operation": "add_1000", + "ready_ms": 112.8, + "received_bytes": 2517229, + "redis_bytes": 14618736, + "search_p50_ns": 1833, + "search_p95_ns": 7542, + "search_p99_ns": 33916, + "search_samples": 99, + "sent_bytes": 2421842 + }, + { + "commit_ms": 36.877, + "commit_to_ready_ms": 60.057, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 105136128, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 96.934, + "received_bytes": 2517230, + "redis_bytes": 15321152, + "search_p50_ns": 1958, + "search_p95_ns": 4625, + "search_p99_ns": 6666, + "search_samples": 89, + "sent_bytes": 2398841 + }, + { + "commit_ms": 37.098, + "commit_to_ready_ms": 70.063, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 105332736, + "n": 100000, + "operation": "add_1000", + "ready_ms": 107.161, + "received_bytes": 2517237, + "redis_bytes": 16010736, + "search_p50_ns": 1959, + "search_p95_ns": 8583, + "search_p99_ns": 10875, + "search_samples": 99, + "sent_bytes": 2421842 + }, + { + "commit_ms": 36.415, + "commit_to_ready_ms": 60.072, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 105332736, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 96.488, + "received_bytes": 2517237, + "redis_bytes": 16716256, + "search_p50_ns": 1917, + "search_p95_ns": 8167, + "search_p99_ns": 12500, + "search_samples": 83, + "sent_bytes": 2398841 + }, + { + "commit_ms": 165.552, + "commit_to_ready_ms": 160.096, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 144900096, + "n": 100000, + "operation": "full_replace", + "ready_ms": 325.648, + "received_bytes": 6680055, + "redis_bytes": 21912560, + "search_p50_ns": 1959, + "search_p95_ns": 7584, + "search_p99_ns": 17875, + "search_samples": 300, + "sent_bytes": 8727710 + } + ], + "startup_ms": 126.503, + "prune": { + "ms": 14.432, + "generations": 14, + "chunks": 4990, + "redis_bytes": 7503600 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=100000 kind=shared seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469773778454 uptime_in_seconds:62 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084877 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 100000, + "kind": "shared", + "repeat": 2, + "measurements": [ + { + "commit_ms": 68.084, + "commit_to_ready_ms": 170.072, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 54231040, + "n": 100000, + "operation": "initial_load", + "ready_ms": 238.157, + "received_bytes": 3414764, + "redis_bytes": 6619360, + "search_p50_ns": 583, + "search_p95_ns": 7500, + "search_p99_ns": 11791, + "search_samples": 236, + "sent_bytes": 7847566 + }, + { + "commit_ms": 151.971, + "commit_to_ready_ms": 0.029, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 73449472, + "n": 100000, + "operation": "identical_replace", + "ready_ms": 152, + "received_bytes": 3233881, + "redis_bytes": 6621104, + "search_p50_ns": 2625, + "search_p95_ns": 8584, + "search_p99_ns": 27500, + "search_samples": 148, + "sent_bytes": 683693 + }, + { + "commit_ms": 6.563, + "commit_to_ready_ms": 60.088, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 93454336, + "n": 100000, + "operation": "add_1_repeat_0", + "ready_ms": 66.652, + "received_bytes": 1390676, + "redis_bytes": 8079680, + "search_p50_ns": 2583, + "search_p95_ns": 9833, + "search_p99_ns": 28125, + "search_samples": 60, + "sent_bytes": 700189 + }, + { + "commit_ms": 6.31, + "commit_to_ready_ms": 50.112, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 98123776, + "n": 100000, + "operation": "remove_1_repeat_0", + "ready_ms": 56.422, + "received_bytes": 1390681, + "redis_bytes": 8785152, + "search_p50_ns": 3209, + "search_p95_ns": 11833, + "search_p99_ns": 13833, + "search_samples": 51, + "sent_bytes": 700171 + }, + { + "commit_ms": 5.252, + "commit_to_ready_ms": 40.056, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 98304000, + "n": 100000, + "operation": "add_1_repeat_1", + "ready_ms": 45.309, + "received_bytes": 1390681, + "redis_bytes": 9491648, + "search_p50_ns": 1792, + "search_p95_ns": 9667, + "search_p99_ns": 9667, + "search_samples": 31, + "sent_bytes": 700189 + }, + { + "commit_ms": 6.304, + "commit_to_ready_ms": 50.111, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 98369536, + "n": 100000, + "operation": "remove_1_repeat_1", + "ready_ms": 56.416, + "received_bytes": 1390682, + "redis_bytes": 10197088, + "search_p50_ns": 2000, + "search_p95_ns": 4625, + "search_p99_ns": 10292, + "search_samples": 51, + "sent_bytes": 700171 + }, + { + "commit_ms": 7.225, + "commit_to_ready_ms": 40.062, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 98385920, + "n": 100000, + "operation": "add_1_repeat_2", + "ready_ms": 47.288, + "received_bytes": 1390933, + "redis_bytes": 10903632, + "search_p50_ns": 1958, + "search_p95_ns": 7500, + "search_p99_ns": 14750, + "search_samples": 43, + "sent_bytes": 700314 + }, + { + "commit_ms": 6.714, + "commit_to_ready_ms": 50.163, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 98844672, + "n": 100000, + "operation": "remove_1_repeat_2", + "ready_ms": 56.878, + "received_bytes": 1390935, + "redis_bytes": 11609104, + "search_p50_ns": 1750, + "search_p95_ns": 7166, + "search_p99_ns": 8875, + "search_samples": 52, + "sent_bytes": 700296 + }, + { + "commit_ms": 6.785, + "commit_to_ready_ms": 40.135, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 99254272, + "n": 100000, + "operation": "add_1", + "ready_ms": 46.92, + "received_bytes": 1390782, + "redis_bytes": 12315632, + "search_p50_ns": 1750, + "search_p95_ns": 7750, + "search_p99_ns": 9291, + "search_samples": 29, + "sent_bytes": 700241 + }, + { + "commit_ms": 9.231, + "commit_to_ready_ms": 40.128, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 99254272, + "n": 100000, + "operation": "remove_1", + "ready_ms": 49.359, + "received_bytes": 1390789, + "redis_bytes": 13021104, + "search_p50_ns": 1917, + "search_p95_ns": 3541, + "search_p99_ns": 12208, + "search_samples": 40, + "sent_bytes": 700223 + }, + { + "commit_ms": 50.699, + "commit_to_ready_ms": 70.116, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 99287040, + "n": 100000, + "operation": "add_1000", + "ready_ms": 120.815, + "received_bytes": 2517253, + "redis_bytes": 14637664, + "search_p50_ns": 1625, + "search_p95_ns": 4375, + "search_p99_ns": 6125, + "search_samples": 109, + "sent_bytes": 2421842 + }, + { + "commit_ms": 33.07, + "commit_to_ready_ms": 60.049, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 99368960, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 93.119, + "received_bytes": 2517255, + "redis_bytes": 15339120, + "search_p50_ns": 1750, + "search_p95_ns": 5708, + "search_p99_ns": 11833, + "search_samples": 87, + "sent_bytes": 2398841 + }, + { + "commit_ms": 31.832, + "commit_to_ready_ms": 70.124, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 104103936, + "n": 100000, + "operation": "add_1000", + "ready_ms": 101.957, + "received_bytes": 2517251, + "redis_bytes": 16009152, + "search_p50_ns": 1667, + "search_p95_ns": 5958, + "search_p99_ns": 20292, + "search_samples": 95, + "sent_bytes": 2421842 + }, + { + "commit_ms": 31.598, + "commit_to_ready_ms": 80.09, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 104120320, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 111.688, + "received_bytes": 2517256, + "redis_bytes": 16714656, + "search_p50_ns": 1833, + "search_p95_ns": 7625, + "search_p99_ns": 12459, + "search_samples": 103, + "sent_bytes": 2398841 + }, + { + "commit_ms": 143.898, + "commit_to_ready_ms": 150.133, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 151617536, + "n": 100000, + "operation": "full_replace", + "ready_ms": 294.031, + "received_bytes": 6680073, + "redis_bytes": 21228336, + "search_p50_ns": 1542, + "search_p95_ns": 3709, + "search_p99_ns": 12459, + "search_samples": 261, + "sent_bytes": 8727710 + } + ], + "startup_ms": 145.227, + "prune": { + "ms": 13.686, + "generations": 14, + "chunks": 4990, + "redis_bytes": 6819664 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=100000 kind=shared seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469840496171 uptime_in_seconds:129 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084944 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 100000, + "kind": "shared", + "repeat": 3, + "measurements": [ + { + "commit_ms": 59.808, + "commit_to_ready_ms": 140.155, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 61014016, + "n": 100000, + "operation": "initial_load", + "ready_ms": 199.963, + "received_bytes": 3414469, + "redis_bytes": 7308592, + "search_p50_ns": 417, + "search_p95_ns": 2083, + "search_p99_ns": 7833, + "search_samples": 196, + "sent_bytes": 7847320 + }, + { + "commit_ms": 125.055, + "commit_to_ready_ms": 0.023, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 72089600, + "n": 100000, + "operation": "identical_replace", + "ready_ms": 125.079, + "received_bytes": 3233886, + "redis_bytes": 6629152, + "search_p50_ns": 1917, + "search_p95_ns": 3167, + "search_p99_ns": 13167, + "search_samples": 118, + "sent_bytes": 683693 + }, + { + "commit_ms": 5.045, + "commit_to_ready_ms": 50.102, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 88276992, + "n": 100000, + "operation": "add_1_repeat_0", + "ready_ms": 55.147, + "received_bytes": 1390680, + "redis_bytes": 8085136, + "search_p50_ns": 1792, + "search_p95_ns": 9709, + "search_p99_ns": 17209, + "search_samples": 51, + "sent_bytes": 700189 + }, + { + "commit_ms": 5.04, + "commit_to_ready_ms": 40.046, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96239616, + "n": 100000, + "operation": "remove_1_repeat_0", + "ready_ms": 45.086, + "received_bytes": 1390680, + "redis_bytes": 8791616, + "search_p50_ns": 1917, + "search_p95_ns": 8916, + "search_p99_ns": 8917, + "search_samples": 40, + "sent_bytes": 700171 + }, + { + "commit_ms": 5.598, + "commit_to_ready_ms": 50.099, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96419840, + "n": 100000, + "operation": "add_1_repeat_1", + "ready_ms": 55.697, + "received_bytes": 1390686, + "redis_bytes": 9498000, + "search_p50_ns": 2083, + "search_p95_ns": 8625, + "search_p99_ns": 17875, + "search_samples": 50, + "sent_bytes": 700189 + }, + { + "commit_ms": 6.434, + "commit_to_ready_ms": 40.092, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96468992, + "n": 100000, + "operation": "remove_1_repeat_1", + "ready_ms": 46.527, + "received_bytes": 1390685, + "redis_bytes": 10205488, + "search_p50_ns": 2042, + "search_p95_ns": 8875, + "search_p99_ns": 10208, + "search_samples": 35, + "sent_bytes": 700171 + }, + { + "commit_ms": 6.703, + "commit_to_ready_ms": 50.116, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96534528, + "n": 100000, + "operation": "add_1_repeat_2", + "ready_ms": 56.819, + "received_bytes": 1390938, + "redis_bytes": 10912032, + "search_p50_ns": 2000, + "search_p95_ns": 8333, + "search_p99_ns": 10417, + "search_samples": 52, + "sent_bytes": 700314 + }, + { + "commit_ms": 8.984, + "commit_to_ready_ms": 40.159, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96534528, + "n": 100000, + "operation": "remove_1_repeat_2", + "ready_ms": 49.144, + "received_bytes": 1390938, + "redis_bytes": 11617472, + "search_p50_ns": 2000, + "search_p95_ns": 7833, + "search_p99_ns": 9000, + "search_samples": 45, + "sent_bytes": 700296 + }, + { + "commit_ms": 8.713, + "commit_to_ready_ms": 40.191, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96600064, + "n": 100000, + "operation": "add_1", + "ready_ms": 48.904, + "received_bytes": 1390791, + "redis_bytes": 12323984, + "search_p50_ns": 1917, + "search_p95_ns": 7917, + "search_p99_ns": 13625, + "search_samples": 42, + "sent_bytes": 700241 + }, + { + "commit_ms": 8.688, + "commit_to_ready_ms": 40.2, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96927744, + "n": 100000, + "operation": "remove_1", + "ready_ms": 48.889, + "received_bytes": 1390792, + "redis_bytes": 13029440, + "search_p50_ns": 2000, + "search_p95_ns": 9083, + "search_p99_ns": 9166, + "search_samples": 34, + "sent_bytes": 700223 + }, + { + "commit_ms": 53.565, + "commit_to_ready_ms": 80.093, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96976896, + "n": 100000, + "operation": "add_1000", + "ready_ms": 133.659, + "received_bytes": 2517331, + "redis_bytes": 14626608, + "search_p50_ns": 1833, + "search_p95_ns": 8208, + "search_p99_ns": 10125, + "search_samples": 116, + "sent_bytes": 2421943 + }, + { + "commit_ms": 36.682, + "commit_to_ready_ms": 70.114, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 96993280, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 106.797, + "received_bytes": 2517259, + "redis_bytes": 15350208, + "search_p50_ns": 1959, + "search_p95_ns": 8417, + "search_p99_ns": 15500, + "search_samples": 90, + "sent_bytes": 2398841 + }, + { + "commit_ms": 37.772, + "commit_to_ready_ms": 60.165, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 97009664, + "n": 100000, + "operation": "add_1000", + "ready_ms": 97.938, + "received_bytes": 2517260, + "redis_bytes": 16020256, + "search_p50_ns": 1875, + "search_p95_ns": 7625, + "search_p99_ns": 14625, + "search_samples": 85, + "sent_bytes": 2421842 + }, + { + "commit_ms": 39.4, + "commit_to_ready_ms": 60.074, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 97042432, + "n": 100000, + "operation": "remove_1000", + "ready_ms": 99.475, + "received_bytes": 2517260, + "redis_bytes": 16725760, + "search_p50_ns": 2000, + "search_p95_ns": 7250, + "search_p99_ns": 13000, + "search_samples": 95, + "sent_bytes": 2398841 + }, + { + "commit_ms": 169.806, + "commit_to_ready_ms": 170.175, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 142868480, + "n": 100000, + "operation": "full_replace", + "ready_ms": 339.981, + "received_bytes": 6680077, + "redis_bytes": 21920800, + "search_p50_ns": 1917, + "search_p95_ns": 7167, + "search_p99_ns": 13083, + "search_samples": 332, + "sent_bytes": 8727710 + } + ], + "startup_ms": 128.258, + "prune": { + "ms": 14.323, + "generations": 14, + "chunks": 4990, + "redis_bytes": 6833776 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=100000 kind=shared seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469906726785 uptime_in_seconds:195 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11085010 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 1000000, + "kind": "diverse", + "repeat": 1, + "measurements": [ + { + "commit_ms": 588.094, + "commit_to_ready_ms": 1140.135, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 921763840, + "n": 1000000, + "operation": "initial_load", + "ready_ms": 1728.23, + "received_bytes": 16923733, + "redis_bytes": 21422048, + "search_p50_ns": 459, + "search_p95_ns": 3292, + "search_p99_ns": 9667, + "search_samples": 1679, + "sent_bytes": 21356862 + }, + { + "commit_ms": 577.526, + "commit_to_ready_ms": 0.018, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1207369728, + "n": 1000000, + "operation": "identical_replace", + "ready_ms": 577.544, + "received_bytes": 16742704, + "redis_bytes": 21423552, + "search_p50_ns": 1917, + "search_p95_ns": 4458, + "search_p99_ns": 11166, + "search_samples": 553, + "sent_bytes": 684602 + }, + { + "commit_ms": 5.1, + "commit_to_ready_ms": 900.079, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1778204672, + "n": 1000000, + "operation": "add_1_repeat_0", + "ready_ms": 905.179, + "received_bytes": 1406327, + "redis_bytes": 22199968, + "search_p50_ns": 2042, + "search_p95_ns": 4500, + "search_p99_ns": 11708, + "search_samples": 884, + "sent_bytes": 708019 + }, + { + "commit_ms": 9.07, + "commit_to_ready_ms": 850.12, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2070380544, + "n": 1000000, + "operation": "remove_1_repeat_0", + "ready_ms": 859.191, + "received_bytes": 1406333, + "redis_bytes": 22905424, + "search_p50_ns": 2125, + "search_p95_ns": 4083, + "search_p99_ns": 12792, + "search_samples": 807, + "sent_bytes": 708001 + }, + { + "commit_ms": 9.122, + "commit_to_ready_ms": 830.115, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2070380544, + "n": 1000000, + "operation": "add_1_repeat_1", + "ready_ms": 839.237, + "received_bytes": 1406837, + "redis_bytes": 23595872, + "search_p50_ns": 2083, + "search_p95_ns": 6875, + "search_p99_ns": 13125, + "search_samples": 805, + "sent_bytes": 708275 + }, + { + "commit_ms": 9.166, + "commit_to_ready_ms": 860.099, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2070380544, + "n": 1000000, + "operation": "remove_1_repeat_1", + "ready_ms": 869.265, + "received_bytes": 1406838, + "redis_bytes": 24297168, + "search_p50_ns": 2125, + "search_p95_ns": 4500, + "search_p99_ns": 11083, + "search_samples": 822, + "sent_bytes": 708257 + }, + { + "commit_ms": 7.794, + "commit_to_ready_ms": 1000.172, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2070380544, + "n": 1000000, + "operation": "add_1_repeat_2", + "ready_ms": 1007.966, + "received_bytes": 1405910, + "redis_bytes": 25002912, + "search_p50_ns": 2167, + "search_p95_ns": 9333, + "search_p99_ns": 17875, + "search_samples": 976, + "sent_bytes": 707811 + }, + { + "commit_ms": 9.031, + "commit_to_ready_ms": 980.114, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2070380544, + "n": 1000000, + "operation": "remove_1_repeat_2", + "ready_ms": 989.146, + "received_bytes": 1405909, + "redis_bytes": 25711424, + "search_p50_ns": 3083, + "search_p95_ns": 12708, + "search_p99_ns": 18250, + "search_samples": 963, + "sent_bytes": 707793 + }, + { + "commit_ms": 6.827, + "commit_to_ready_ms": 910.175, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2070380544, + "n": 1000000, + "operation": "add_1", + "ready_ms": 917.002, + "received_bytes": 1405239, + "redis_bytes": 26421408, + "search_p50_ns": 2167, + "search_p95_ns": 6083, + "search_p99_ns": 19000, + "search_samples": 892, + "sent_bytes": 707477 + }, + { + "commit_ms": 9.494, + "commit_to_ready_ms": 850.116, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2070380544, + "n": 1000000, + "operation": "remove_1", + "ready_ms": 859.611, + "received_bytes": 1405242, + "redis_bytes": 27126832, + "search_p50_ns": 2125, + "search_p95_ns": 4084, + "search_p99_ns": 9625, + "search_samples": 819, + "sent_bytes": 707459 + }, + { + "commit_ms": 105.973, + "commit_to_ready_ms": 920.14, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2070429696, + "n": 1000000, + "operation": "add_1000", + "ready_ms": 1026.114, + "received_bytes": 8390029, + "redis_bytes": 31977120, + "search_p50_ns": 2084, + "search_p95_ns": 3916, + "search_p99_ns": 9208, + "search_samples": 984, + "sent_bytes": 5358371 + }, + { + "commit_ms": 114.33, + "commit_to_ready_ms": 1160.051, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2070429696, + "n": 1000000, + "operation": "remove_1000", + "ready_ms": 1274.381, + "received_bytes": 8390040, + "redis_bytes": 32671376, + "search_p50_ns": 2667, + "search_p95_ns": 12333, + "search_p99_ns": 20792, + "search_samples": 1220, + "sent_bytes": 5335371 + }, + { + "commit_ms": 411.714, + "commit_to_ready_ms": 1110.149, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2071314432, + "n": 1000000, + "operation": "add_10000", + "ready_ms": 1521.863, + "received_bytes": 30940778, + "redis_bytes": 51150752, + "search_p50_ns": 2042, + "search_p95_ns": 3792, + "search_p99_ns": 9750, + "search_samples": 1488, + "sent_bytes": 20417840 + }, + { + "commit_ms": 424.67, + "commit_to_ready_ms": 1210.146, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2151759872, + "n": 1000000, + "operation": "remove_10000", + "ready_ms": 1634.816, + "received_bytes": 30940781, + "redis_bytes": 51840176, + "search_p50_ns": 2125, + "search_p95_ns": 6667, + "search_p99_ns": 14666, + "search_samples": 1579, + "sent_bytes": 20177840 + }, + { + "commit_ms": 727.046, + "commit_to_ready_ms": 1490.101, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2623848448, + "n": 1000000, + "operation": "full_replace", + "ready_ms": 2217.147, + "received_bytes": 35497182, + "redis_bytes": 74201424, + "search_p50_ns": 2209, + "search_p95_ns": 8416, + "search_p99_ns": 17458, + "search_samples": 2126, + "sent_bytes": 24036964 + } + ], + "startup_ms": 1111.535, + "prune": { + "ms": 55.808, + "generations": 14, + "chunks": 8729, + "redis_bytes": 24288848 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=1000000 kind=diverse seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469794201272 uptime_in_seconds:83 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084898 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 1000000, + "kind": "diverse", + "repeat": 2, + "measurements": [ + { + "commit_ms": 547.475, + "commit_to_ready_ms": 1160.087, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 841433088, + "n": 1000000, + "operation": "initial_load", + "ready_ms": 1707.563, + "received_bytes": 16923673, + "redis_bytes": 21421568, + "search_p50_ns": 458, + "search_p95_ns": 2625, + "search_p99_ns": 10625, + "search_samples": 1676, + "sent_bytes": 21356761 + }, + { + "commit_ms": 1463.345, + "commit_to_ready_ms": 0.039, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1005355008, + "n": 1000000, + "operation": "identical_replace", + "ready_ms": 1463.385, + "received_bytes": 16743869, + "redis_bytes": 21423040, + "search_p50_ns": 7625, + "search_p95_ns": 24625, + "search_p99_ns": 289459, + "search_samples": 1134, + "sent_bytes": 686218 + }, + { + "commit_ms": 6.316, + "commit_to_ready_ms": 950.102, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1621262336, + "n": 1000000, + "operation": "add_1_repeat_0", + "ready_ms": 956.418, + "received_bytes": 1406334, + "redis_bytes": 22199552, + "search_p50_ns": 2000, + "search_p95_ns": 5042, + "search_p99_ns": 18792, + "search_samples": 921, + "sent_bytes": 708019 + }, + { + "commit_ms": 8.938, + "commit_to_ready_ms": 890.198, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1983201280, + "n": 1000000, + "operation": "remove_1_repeat_0", + "ready_ms": 899.136, + "received_bytes": 1406337, + "redis_bytes": 22905024, + "search_p50_ns": 1875, + "search_p95_ns": 4042, + "search_p99_ns": 9709, + "search_samples": 867, + "sent_bytes": 708001 + }, + { + "commit_ms": 7.316, + "commit_to_ready_ms": 910.109, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2120712192, + "n": 1000000, + "operation": "add_1_repeat_1", + "ready_ms": 917.425, + "received_bytes": 1406843, + "redis_bytes": 23611776, + "search_p50_ns": 1833, + "search_p95_ns": 4541, + "search_p99_ns": 12750, + "search_samples": 884, + "sent_bytes": 708275 + }, + { + "commit_ms": 8.975, + "commit_to_ready_ms": 1070.181, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2120728576, + "n": 1000000, + "operation": "remove_1_repeat_1", + "ready_ms": 1079.156, + "received_bytes": 1406844, + "redis_bytes": 24314144, + "search_p50_ns": 2292, + "search_p95_ns": 12459, + "search_p99_ns": 18291, + "search_samples": 1007, + "sent_bytes": 708257 + }, + { + "commit_ms": 8.587, + "commit_to_ready_ms": 870.167, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2204188672, + "n": 1000000, + "operation": "add_1_repeat_2", + "ready_ms": 878.755, + "received_bytes": 1405914, + "redis_bytes": 25026032, + "search_p50_ns": 2083, + "search_p95_ns": 4083, + "search_p99_ns": 10166, + "search_samples": 848, + "sent_bytes": 707811 + }, + { + "commit_ms": 8.937, + "commit_to_ready_ms": 910.195, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2204319744, + "n": 1000000, + "operation": "remove_1_repeat_2", + "ready_ms": 919.132, + "received_bytes": 1405916, + "redis_bytes": 25731488, + "search_p50_ns": 2125, + "search_p95_ns": 4125, + "search_p99_ns": 9334, + "search_samples": 863, + "sent_bytes": 707793 + }, + { + "commit_ms": 7.502, + "commit_to_ready_ms": 870.111, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2204368896, + "n": 1000000, + "operation": "add_1", + "ready_ms": 877.613, + "received_bytes": 1405246, + "redis_bytes": 26441504, + "search_p50_ns": 2042, + "search_p95_ns": 4000, + "search_p99_ns": 11458, + "search_samples": 865, + "sent_bytes": 707477 + }, + { + "commit_ms": 9.19, + "commit_to_ready_ms": 880.1, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2204385280, + "n": 1000000, + "operation": "remove_1", + "ready_ms": 889.29, + "received_bytes": 1405249, + "redis_bytes": 27143888, + "search_p50_ns": 2125, + "search_p95_ns": 4750, + "search_p99_ns": 14458, + "search_samples": 839, + "sent_bytes": 707459 + }, + { + "commit_ms": 107.725, + "commit_to_ready_ms": 970.137, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2204401664, + "n": 1000000, + "operation": "add_1000", + "ready_ms": 1077.862, + "received_bytes": 8390039, + "redis_bytes": 31975136, + "search_p50_ns": 2041, + "search_p95_ns": 4709, + "search_p99_ns": 13792, + "search_samples": 1024, + "sent_bytes": 5358371 + }, + { + "commit_ms": 106.56, + "commit_to_ready_ms": 910.091, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2204499968, + "n": 1000000, + "operation": "remove_1000", + "ready_ms": 1016.652, + "received_bytes": 8389975, + "redis_bytes": 32680624, + "search_p50_ns": 2125, + "search_p95_ns": 3958, + "search_p99_ns": 8041, + "search_samples": 994, + "sent_bytes": 5335270 + }, + { + "commit_ms": 413.448, + "commit_to_ready_ms": 1110.075, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2205155328, + "n": 1000000, + "operation": "add_10000", + "ready_ms": 1523.524, + "received_bytes": 30940784, + "redis_bytes": 51148176, + "search_p50_ns": 2125, + "search_p95_ns": 3584, + "search_p99_ns": 9333, + "search_samples": 1476, + "sent_bytes": 20417840 + }, + { + "commit_ms": 422.722, + "commit_to_ready_ms": 1090.115, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2205827072, + "n": 1000000, + "operation": "remove_10000", + "ready_ms": 1512.838, + "received_bytes": 30940863, + "redis_bytes": 51830448, + "search_p50_ns": 2125, + "search_p95_ns": 3667, + "search_p99_ns": 9875, + "search_samples": 1456, + "sent_bytes": 20177941 + }, + { + "commit_ms": 693.109, + "commit_to_ready_ms": 1250.106, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2361114624, + "n": 1000000, + "operation": "full_replace", + "ready_ms": 1943.216, + "received_bytes": 35497191, + "redis_bytes": 74197280, + "search_p50_ns": 2084, + "search_p95_ns": 3459, + "search_p99_ns": 8791, + "search_samples": 1880, + "sent_bytes": 24036964 + } + ], + "startup_ms": 1335.888, + "prune": { + "ms": 72.878, + "generations": 14, + "chunks": 8729, + "redis_bytes": 24281472 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=1000000 kind=diverse seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469862061606 uptime_in_seconds:151 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084966 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 1000000, + "kind": "diverse", + "repeat": 3, + "measurements": [ + { + "commit_ms": 498.668, + "commit_to_ready_ms": 1140.161, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 961609728, + "n": 1000000, + "operation": "initial_load", + "ready_ms": 1638.829, + "received_bytes": 16923607, + "redis_bytes": 21428176, + "search_p50_ns": 416, + "search_p95_ns": 1791, + "search_p99_ns": 6583, + "search_samples": 1588, + "sent_bytes": 21356660 + }, + { + "commit_ms": 548.393, + "commit_to_ready_ms": 0.018, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 998129664, + "n": 1000000, + "operation": "identical_replace", + "ready_ms": 548.411, + "received_bytes": 16742650, + "redis_bytes": 21429648, + "search_p50_ns": 1958, + "search_p95_ns": 2750, + "search_p99_ns": 5917, + "search_samples": 529, + "sent_bytes": 684501 + }, + { + "commit_ms": 5.12, + "commit_to_ready_ms": 920.042, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1525383168, + "n": 1000000, + "operation": "add_1_repeat_0", + "ready_ms": 925.162, + "received_bytes": 1406344, + "redis_bytes": 22206080, + "search_p50_ns": 2000, + "search_p95_ns": 3875, + "search_p99_ns": 19541, + "search_samples": 883, + "sent_bytes": 708019 + }, + { + "commit_ms": 7.492, + "commit_to_ready_ms": 890.101, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1784365056, + "n": 1000000, + "operation": "remove_1_repeat_0", + "ready_ms": 897.593, + "received_bytes": 1406350, + "redis_bytes": 22911520, + "search_p50_ns": 2125, + "search_p95_ns": 4834, + "search_p99_ns": 10500, + "search_samples": 846, + "sent_bytes": 708001 + }, + { + "commit_ms": 14.536, + "commit_to_ready_ms": 870.154, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1964326912, + "n": 1000000, + "operation": "add_1_repeat_1", + "ready_ms": 884.691, + "received_bytes": 1406926, + "redis_bytes": 23622496, + "search_p50_ns": 2084, + "search_p95_ns": 4417, + "search_p99_ns": 9334, + "search_samples": 855, + "sent_bytes": 708376 + }, + { + "commit_ms": 9.03, + "commit_to_ready_ms": 860.084, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1964343296, + "n": 1000000, + "operation": "remove_1_repeat_1", + "ready_ms": 869.114, + "received_bytes": 1406856, + "redis_bytes": 24323808, + "search_p50_ns": 2167, + "search_p95_ns": 4166, + "search_p99_ns": 9042, + "search_samples": 831, + "sent_bytes": 708257 + }, + { + "commit_ms": 9.575, + "commit_to_ready_ms": 880.153, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1964343296, + "n": 1000000, + "operation": "add_1_repeat_2", + "ready_ms": 889.728, + "received_bytes": 1405929, + "redis_bytes": 25034672, + "search_p50_ns": 2083, + "search_p95_ns": 4125, + "search_p99_ns": 10333, + "search_samples": 866, + "sent_bytes": 707811 + }, + { + "commit_ms": 9.56, + "commit_to_ready_ms": 890.132, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1964343296, + "n": 1000000, + "operation": "remove_1_repeat_2", + "ready_ms": 899.693, + "received_bytes": 1405930, + "redis_bytes": 25738112, + "search_p50_ns": 2167, + "search_p95_ns": 6959, + "search_p99_ns": 18000, + "search_samples": 856, + "sent_bytes": 707793 + }, + { + "commit_ms": 9.221, + "commit_to_ready_ms": 870.102, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1964343296, + "n": 1000000, + "operation": "add_1", + "ready_ms": 879.323, + "received_bytes": 1405253, + "redis_bytes": 26448064, + "search_p50_ns": 2125, + "search_p95_ns": 4166, + "search_p99_ns": 10416, + "search_samples": 853, + "sent_bytes": 707477 + }, + { + "commit_ms": 9.392, + "commit_to_ready_ms": 940.134, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1964343296, + "n": 1000000, + "operation": "remove_1", + "ready_ms": 949.527, + "received_bytes": 1405260, + "redis_bytes": 27153504, + "search_p50_ns": 2459, + "search_p95_ns": 13459, + "search_p99_ns": 20458, + "search_samples": 908, + "sent_bytes": 707459 + }, + { + "commit_ms": 119.485, + "commit_to_ready_ms": 1010.1, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1964376064, + "n": 1000000, + "operation": "add_1000", + "ready_ms": 1129.586, + "received_bytes": 8390051, + "redis_bytes": 31974704, + "search_p50_ns": 2208, + "search_p95_ns": 8167, + "search_p99_ns": 20750, + "search_samples": 1089, + "sent_bytes": 5358371 + }, + { + "commit_ms": 113.402, + "commit_to_ready_ms": 930.079, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1964408832, + "n": 1000000, + "operation": "remove_1000", + "ready_ms": 1043.482, + "received_bytes": 8390058, + "redis_bytes": 32683264, + "search_p50_ns": 2125, + "search_p95_ns": 4917, + "search_p99_ns": 11750, + "search_samples": 997, + "sent_bytes": 5335371 + }, + { + "commit_ms": 418.374, + "commit_to_ready_ms": 1110.064, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 1967226880, + "n": 1000000, + "operation": "add_10000", + "ready_ms": 1528.439, + "received_bytes": 30940795, + "redis_bytes": 51156896, + "search_p50_ns": 2083, + "search_p95_ns": 3833, + "search_p99_ns": 9625, + "search_samples": 1486, + "sent_bytes": 20417840 + }, + { + "commit_ms": 402.656, + "commit_to_ready_ms": 1100.122, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2306818048, + "n": 1000000, + "operation": "remove_10000", + "ready_ms": 1502.778, + "received_bytes": 30940797, + "redis_bytes": 51846304, + "search_p50_ns": 2166, + "search_p95_ns": 3666, + "search_p99_ns": 9916, + "search_samples": 1449, + "sent_bytes": 20177840 + }, + { + "commit_ms": 798.557, + "commit_to_ready_ms": 1300.087, + "delta_search": false, + "kind": "diverse", + "max_rss_bytes": 2571288576, + "n": 1000000, + "operation": "full_replace", + "ready_ms": 2098.645, + "received_bytes": 35497341, + "redis_bytes": 74208272, + "search_p50_ns": 2250, + "search_p95_ns": 10125, + "search_p99_ns": 21125, + "search_samples": 2016, + "sent_bytes": 24037166 + } + ], + "startup_ms": 1261.653, + "prune": { + "ms": 57.034, + "generations": 14, + "chunks": 8729, + "redis_bytes": 24296704 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=1000000 kind=diverse seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469926464531 uptime_in_seconds:215 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11085030 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 1000000, + "kind": "korean", + "repeat": 1, + "measurements": [ + { + "commit_ms": 732.763, + "commit_to_ready_ms": 1440.15, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 1230798848, + "n": 1000000, + "operation": "initial_load", + "ready_ms": 2172.914, + "received_bytes": 36924021, + "redis_bytes": 44741600, + "search_p50_ns": 708, + "search_p95_ns": 2667, + "search_p99_ns": 10625, + "search_samples": 2147, + "sent_bytes": 41357232 + }, + { + "commit_ms": 833.617, + "commit_to_ready_ms": 0.017, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 1518764032, + "n": 1000000, + "operation": "identical_replace", + "ready_ms": 833.634, + "received_bytes": 36743137, + "redis_bytes": 44757424, + "search_p50_ns": 2458, + "search_p95_ns": 8750, + "search_p99_ns": 16166, + "search_samples": 816, + "sent_bytes": 685107 + }, + { + "commit_ms": 5.283, + "commit_to_ready_ms": 1170.061, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 1991589888, + "n": 1000000, + "operation": "add_1_repeat_0", + "ready_ms": 1175.345, + "received_bytes": 1414741, + "redis_bytes": 45538992, + "search_p50_ns": 2792, + "search_p95_ns": 10833, + "search_p99_ns": 23500, + "search_samples": 1149, + "sent_bytes": 712223 + }, + { + "commit_ms": 8.663, + "commit_to_ready_ms": 1260.161, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2271084544, + "n": 1000000, + "operation": "remove_1_repeat_0", + "ready_ms": 1268.825, + "received_bytes": 1414746, + "redis_bytes": 46223984, + "search_p50_ns": 3542, + "search_p95_ns": 15041, + "search_p99_ns": 22041, + "search_samples": 1211, + "sent_bytes": 712205 + }, + { + "commit_ms": 7.224, + "commit_to_ready_ms": 1150.065, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2437758976, + "n": 1000000, + "operation": "add_1_repeat_1", + "ready_ms": 1157.289, + "received_bytes": 1415603, + "redis_bytes": 46924640, + "search_p50_ns": 2875, + "search_p95_ns": 11833, + "search_p99_ns": 28291, + "search_samples": 1122, + "sent_bytes": 712655 + }, + { + "commit_ms": 9.197, + "commit_to_ready_ms": 1120.082, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2437758976, + "n": 1000000, + "operation": "remove_1_repeat_1", + "ready_ms": 1129.279, + "received_bytes": 1415604, + "redis_bytes": 47614752, + "search_p50_ns": 2416, + "search_p95_ns": 7875, + "search_p99_ns": 25209, + "search_samples": 1069, + "sent_bytes": 712637 + }, + { + "commit_ms": 9.808, + "commit_to_ready_ms": 1140.165, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2437758976, + "n": 1000000, + "operation": "add_1_repeat_2", + "ready_ms": 1149.974, + "received_bytes": 1415026, + "redis_bytes": 48331824, + "search_p50_ns": 2542, + "search_p95_ns": 11209, + "search_p99_ns": 19833, + "search_samples": 1132, + "sent_bytes": 712367 + }, + { + "commit_ms": 6.978, + "commit_to_ready_ms": 1180.189, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2437791744, + "n": 1000000, + "operation": "remove_1_repeat_2", + "ready_ms": 1187.167, + "received_bytes": 1415022, + "redis_bytes": 49039328, + "search_p50_ns": 2875, + "search_p95_ns": 11708, + "search_p99_ns": 23791, + "search_samples": 1158, + "sent_bytes": 712349 + }, + { + "commit_ms": 8.644, + "commit_to_ready_ms": 1170.177, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2437791744, + "n": 1000000, + "operation": "add_1", + "ready_ms": 1178.821, + "received_bytes": 1414886, + "redis_bytes": 49759536, + "search_p50_ns": 2750, + "search_p95_ns": 12834, + "search_p99_ns": 33291, + "search_samples": 1134, + "sent_bytes": 712297 + }, + { + "commit_ms": 8.196, + "commit_to_ready_ms": 1170.081, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2437791744, + "n": 1000000, + "operation": "remove_1", + "ready_ms": 1178.278, + "received_bytes": 1414887, + "redis_bytes": 50457728, + "search_p50_ns": 2875, + "search_p95_ns": 13000, + "search_p99_ns": 26084, + "search_samples": 1126, + "sent_bytes": 712279 + }, + { + "commit_ms": 156.345, + "commit_to_ready_ms": 1250.077, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2461040640, + "n": 1000000, + "operation": "add_1000", + "ready_ms": 1406.422, + "received_bytes": 17126502, + "redis_bytes": 60400032, + "search_p50_ns": 2750, + "search_p95_ns": 11791, + "search_p99_ns": 24417, + "search_samples": 1359, + "sent_bytes": 9726670 + }, + { + "commit_ms": 164.957, + "commit_to_ready_ms": 1120.164, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2461089792, + "n": 1000000, + "operation": "remove_1000", + "ready_ms": 1285.121, + "received_bytes": 17126515, + "redis_bytes": 61109472, + "search_p50_ns": 2625, + "search_p95_ns": 7750, + "search_p99_ns": 17875, + "search_samples": 1244, + "sent_bytes": 9703670 + }, + { + "commit_ms": 622.861, + "commit_to_ready_ms": 1400.152, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2638249984, + "n": 1000000, + "operation": "add_10000", + "ready_ms": 2023.013, + "received_bytes": 67459495, + "redis_bytes": 100700256, + "search_p50_ns": 2583, + "search_p95_ns": 5084, + "search_p99_ns": 13833, + "search_samples": 1982, + "sent_bytes": 38677531 + }, + { + "commit_ms": 688.182, + "commit_to_ready_ms": 1450.062, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2866479104, + "n": 1000000, + "operation": "remove_10000", + "ready_ms": 2138.244, + "received_bytes": 67459499, + "redis_bytes": 101389120, + "search_p50_ns": 2750, + "search_p95_ns": 12958, + "search_p99_ns": 20667, + "search_samples": 2079, + "sent_bytes": 38437510 + }, + { + "commit_ms": 1004.574, + "commit_to_ready_ms": 1800.108, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 3179053056, + "n": 1000000, + "operation": "full_replace", + "ready_ms": 2804.683, + "received_bytes": 75498153, + "redis_bytes": 145529008, + "search_p50_ns": 2667, + "search_p95_ns": 12292, + "search_p99_ns": 22834, + "search_samples": 2714, + "sent_bytes": 44038035 + } + ], + "startup_ms": 1530.136, + "prune": { + "ms": 54.755, + "generations": 14, + "chunks": 8729, + "redis_bytes": 46075568 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=1000000 kind=korean seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469813015630 uptime_in_seconds:102 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084916 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 1000000, + "kind": "korean", + "repeat": 2, + "measurements": [ + { + "commit_ms": 721.851, + "commit_to_ready_ms": 1360.152, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 1238892544, + "n": 1000000, + "operation": "initial_load", + "ready_ms": 2082.004, + "received_bytes": 36923957, + "redis_bytes": 44749392, + "search_p50_ns": 667, + "search_p95_ns": 1959, + "search_p99_ns": 9458, + "search_samples": 2035, + "sent_bytes": 41357131 + }, + { + "commit_ms": 877.111, + "commit_to_ready_ms": 0.018, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 1517174784, + "n": 1000000, + "operation": "identical_replace", + "ready_ms": 877.13, + "received_bytes": 36743143, + "redis_bytes": 44765216, + "search_p50_ns": 2334, + "search_p95_ns": 3792, + "search_p99_ns": 10084, + "search_samples": 855, + "sent_bytes": 685107 + }, + { + "commit_ms": 5.18, + "commit_to_ready_ms": 1080.049, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 1989902336, + "n": 1000000, + "operation": "add_1_repeat_0", + "ready_ms": 1085.229, + "received_bytes": 1414747, + "redis_bytes": 45546784, + "search_p50_ns": 2500, + "search_p95_ns": 4791, + "search_p99_ns": 12667, + "search_samples": 1065, + "sent_bytes": 712223 + }, + { + "commit_ms": 9.445, + "commit_to_ready_ms": 990.153, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2269413376, + "n": 1000000, + "operation": "remove_1_repeat_0", + "ready_ms": 999.598, + "received_bytes": 1414752, + "redis_bytes": 46252272, + "search_p50_ns": 2625, + "search_p95_ns": 4542, + "search_p99_ns": 11500, + "search_samples": 968, + "sent_bytes": 712205 + }, + { + "commit_ms": 9.708, + "commit_to_ready_ms": 1000.196, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2269806592, + "n": 1000000, + "operation": "add_1_repeat_1", + "ready_ms": 1009.905, + "received_bytes": 1415609, + "redis_bytes": 46952992, + "search_p50_ns": 2583, + "search_p95_ns": 4541, + "search_p99_ns": 10792, + "search_samples": 976, + "sent_bytes": 712655 + }, + { + "commit_ms": 9.193, + "commit_to_ready_ms": 990.103, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2269822976, + "n": 1000000, + "operation": "remove_1_repeat_1", + "ready_ms": 999.296, + "received_bytes": 1415610, + "redis_bytes": 47644080, + "search_p50_ns": 2625, + "search_p95_ns": 4833, + "search_p99_ns": 11833, + "search_samples": 975, + "sent_bytes": 712637 + }, + { + "commit_ms": 9.533, + "commit_to_ready_ms": 1010.137, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2270412800, + "n": 1000000, + "operation": "add_1_repeat_2", + "ready_ms": 1019.67, + "received_bytes": 1415032, + "redis_bytes": 48366240, + "search_p50_ns": 2542, + "search_p95_ns": 6417, + "search_p99_ns": 18583, + "search_samples": 981, + "sent_bytes": 712367 + }, + { + "commit_ms": 9.461, + "commit_to_ready_ms": 980.12, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2270412800, + "n": 1000000, + "operation": "remove_1_repeat_2", + "ready_ms": 989.582, + "received_bytes": 1415034, + "redis_bytes": 49079952, + "search_p50_ns": 2583, + "search_p95_ns": 4417, + "search_p99_ns": 16541, + "search_samples": 945, + "sent_bytes": 712349 + }, + { + "commit_ms": 9.215, + "commit_to_ready_ms": 1010.106, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2293776384, + "n": 1000000, + "operation": "add_1", + "ready_ms": 1019.321, + "received_bytes": 1414891, + "redis_bytes": 49796048, + "search_p50_ns": 2542, + "search_p95_ns": 4708, + "search_p99_ns": 12000, + "search_samples": 971, + "sent_bytes": 712297 + }, + { + "commit_ms": 8.064, + "commit_to_ready_ms": 990.084, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2293792768, + "n": 1000000, + "operation": "remove_1", + "ready_ms": 998.148, + "received_bytes": 1414894, + "redis_bytes": 50486160, + "search_p50_ns": 2625, + "search_p95_ns": 4459, + "search_p99_ns": 9542, + "search_samples": 953, + "sent_bytes": 712279 + }, + { + "commit_ms": 149.459, + "commit_to_ready_ms": 1090.101, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2293809152, + "n": 1000000, + "operation": "add_1000", + "ready_ms": 1239.561, + "received_bytes": 17126508, + "redis_bytes": 60412992, + "search_p50_ns": 2458, + "search_p95_ns": 4125, + "search_p99_ns": 10000, + "search_samples": 1211, + "sent_bytes": 9726670 + }, + { + "commit_ms": 157.516, + "commit_to_ready_ms": 1090.084, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2293809152, + "n": 1000000, + "operation": "remove_1000", + "ready_ms": 1247.601, + "received_bytes": 17126522, + "redis_bytes": 61114256, + "search_p50_ns": 2541, + "search_p95_ns": 5000, + "search_p99_ns": 13875, + "search_samples": 1189, + "sent_bytes": 9703670 + }, + { + "commit_ms": 585.271, + "commit_to_ready_ms": 1350.054, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2489532416, + "n": 1000000, + "operation": "add_10000", + "ready_ms": 1935.325, + "received_bytes": 67459358, + "redis_bytes": 100709616, + "search_p50_ns": 2459, + "search_p95_ns": 4000, + "search_p99_ns": 9875, + "search_samples": 1900, + "sent_bytes": 38677329 + }, + { + "commit_ms": 594.51, + "commit_to_ready_ms": 1360.093, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2956050432, + "n": 1000000, + "operation": "remove_10000", + "ready_ms": 1954.603, + "received_bytes": 67459362, + "redis_bytes": 101383136, + "search_p50_ns": 2542, + "search_p95_ns": 4250, + "search_p99_ns": 12583, + "search_samples": 1901, + "sent_bytes": 38437308 + }, + { + "commit_ms": 1067.724, + "commit_to_ready_ms": 1510.115, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 3283238912, + "n": 1000000, + "operation": "full_replace", + "ready_ms": 2577.84, + "received_bytes": 75498231, + "redis_bytes": 145536944, + "search_p50_ns": 2583, + "search_p95_ns": 4250, + "search_p99_ns": 10250, + "search_samples": 2518, + "sent_bytes": 44038136 + } + ], + "startup_ms": 1342.814, + "prune": { + "ms": 60.335, + "generations": 14, + "chunks": 8729, + "redis_bytes": 46081360 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=1000000 kind=korean seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469881597684 uptime_in_seconds:170 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084985 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 1000000, + "kind": "korean", + "repeat": 3, + "measurements": [ + { + "commit_ms": 731.411, + "commit_to_ready_ms": 1380.093, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 1240662016, + "n": 1000000, + "operation": "initial_load", + "ready_ms": 2111.504, + "received_bytes": 36924035, + "redis_bytes": 44748256, + "search_p50_ns": 666, + "search_p95_ns": 2291, + "search_p99_ns": 9667, + "search_samples": 2060, + "sent_bytes": 41357232 + }, + { + "commit_ms": 867.615, + "commit_to_ready_ms": 0.018, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 1309851648, + "n": 1000000, + "operation": "identical_replace", + "ready_ms": 867.633, + "received_bytes": 36743148, + "redis_bytes": 44764080, + "search_p50_ns": 2334, + "search_p95_ns": 3917, + "search_p99_ns": 7833, + "search_samples": 841, + "sent_bytes": 685107 + }, + { + "commit_ms": 5.156, + "commit_to_ready_ms": 1070.043, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2040430592, + "n": 1000000, + "operation": "add_1_repeat_0", + "ready_ms": 1075.2, + "received_bytes": 1414824, + "redis_bytes": 45545648, + "search_p50_ns": 2583, + "search_p95_ns": 5250, + "search_p99_ns": 11958, + "search_samples": 1039, + "sent_bytes": 712324 + }, + { + "commit_ms": 9.219, + "commit_to_ready_ms": 1020.107, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2077376512, + "n": 1000000, + "operation": "remove_1_repeat_0", + "ready_ms": 1029.326, + "received_bytes": 1414757, + "redis_bytes": 46251120, + "search_p50_ns": 2708, + "search_p95_ns": 5292, + "search_p99_ns": 11291, + "search_samples": 980, + "sent_bytes": 712205 + }, + { + "commit_ms": 9.485, + "commit_to_ready_ms": 1010.133, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2209939456, + "n": 1000000, + "operation": "add_1_repeat_1", + "ready_ms": 1019.618, + "received_bytes": 1415614, + "redis_bytes": 46931296, + "search_p50_ns": 2583, + "search_p95_ns": 5125, + "search_p99_ns": 12792, + "search_samples": 977, + "sent_bytes": 712655 + }, + { + "commit_ms": 9.05, + "commit_to_ready_ms": 1210.116, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2243084288, + "n": 1000000, + "operation": "remove_1_repeat_1", + "ready_ms": 1219.167, + "received_bytes": 1415610, + "redis_bytes": 47621360, + "search_p50_ns": 3166, + "search_p95_ns": 14833, + "search_p99_ns": 23709, + "search_samples": 1177, + "sent_bytes": 712637 + }, + { + "commit_ms": 10.726, + "commit_to_ready_ms": 1010.179, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2263007232, + "n": 1000000, + "operation": "add_1_repeat_2", + "ready_ms": 1020.905, + "received_bytes": 1415038, + "redis_bytes": 48338384, + "search_p50_ns": 2667, + "search_p95_ns": 5041, + "search_p99_ns": 12458, + "search_samples": 971, + "sent_bytes": 712367 + }, + { + "commit_ms": 7.523, + "commit_to_ready_ms": 990.151, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2263007232, + "n": 1000000, + "operation": "remove_1_repeat_2", + "ready_ms": 997.674, + "received_bytes": 1415037, + "redis_bytes": 49045856, + "search_p50_ns": 2625, + "search_p95_ns": 5125, + "search_p99_ns": 13833, + "search_samples": 960, + "sent_bytes": 712349 + }, + { + "commit_ms": 6.501, + "commit_to_ready_ms": 1000.144, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2263007232, + "n": 1000000, + "operation": "add_1", + "ready_ms": 1006.646, + "received_bytes": 1414897, + "redis_bytes": 49766096, + "search_p50_ns": 2667, + "search_p95_ns": 4583, + "search_p99_ns": 13292, + "search_samples": 971, + "sent_bytes": 712297 + }, + { + "commit_ms": 9.44, + "commit_to_ready_ms": 1000.151, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2263007232, + "n": 1000000, + "operation": "remove_1", + "ready_ms": 1009.591, + "received_bytes": 1414898, + "redis_bytes": 50479760, + "search_p50_ns": 2584, + "search_p95_ns": 5542, + "search_p99_ns": 12083, + "search_samples": 983, + "sent_bytes": 712279 + }, + { + "commit_ms": 148.523, + "commit_to_ready_ms": 1100.13, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2353528832, + "n": 1000000, + "operation": "add_1000", + "ready_ms": 1248.653, + "received_bytes": 17126519, + "redis_bytes": 60399088, + "search_p50_ns": 2500, + "search_p95_ns": 4333, + "search_p99_ns": 11708, + "search_samples": 1208, + "sent_bytes": 9726670 + }, + { + "commit_ms": 157.69, + "commit_to_ready_ms": 1090.128, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2353676288, + "n": 1000000, + "operation": "remove_1000", + "ready_ms": 1247.819, + "received_bytes": 17126526, + "redis_bytes": 61127968, + "search_p50_ns": 2584, + "search_p95_ns": 4833, + "search_p99_ns": 13000, + "search_samples": 1199, + "sent_bytes": 9703670 + }, + { + "commit_ms": 590.595, + "commit_to_ready_ms": 1330.104, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2554150912, + "n": 1000000, + "operation": "add_10000", + "ready_ms": 1920.7, + "received_bytes": 67459434, + "redis_bytes": 100689712, + "search_p50_ns": 2458, + "search_p95_ns": 3834, + "search_p99_ns": 9791, + "search_samples": 1885, + "sent_bytes": 38677430 + }, + { + "commit_ms": 697.854, + "commit_to_ready_ms": 1380.171, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 2554281984, + "n": 1000000, + "operation": "remove_10000", + "ready_ms": 2078.025, + "received_bytes": 67459511, + "redis_bytes": 101378592, + "search_p50_ns": 2708, + "search_p95_ns": 11542, + "search_p99_ns": 19459, + "search_samples": 2031, + "sent_bytes": 38437510 + }, + { + "commit_ms": 1089.949, + "commit_to_ready_ms": 1650.174, + "delta_search": false, + "kind": "korean", + "max_rss_bytes": 3065528320, + "n": 1000000, + "operation": "full_replace", + "ready_ms": 2740.124, + "received_bytes": 75498308, + "redis_bytes": 145517856, + "search_p50_ns": 2583, + "search_p95_ns": 9333, + "search_p99_ns": 18417, + "search_samples": 2671, + "sent_bytes": 44038237 + } + ], + "startup_ms": 1437.406, + "prune": { + "ms": 62.95, + "generations": 14, + "chunks": 8729, + "redis_bytes": 46067776 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=1000000 kind=korean seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469944912208 uptime_in_seconds:233 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11085048 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 1000000, + "kind": "shared", + "repeat": 1, + "measurements": [ + { + "commit_ms": 388.42, + "commit_to_ready_ms": 810.076, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 417955840, + "n": 1000000, + "operation": "initial_load", + "ready_ms": 1198.497, + "received_bytes": 25923437, + "redis_bytes": 30978688, + "search_p50_ns": 416, + "search_p95_ns": 1459, + "search_p99_ns": 7625, + "search_samples": 1164, + "sent_bytes": 30356458 + }, + { + "commit_ms": 459.194, + "commit_to_ready_ms": 0.017, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 471138304, + "n": 1000000, + "operation": "identical_replace", + "ready_ms": 459.212, + "received_bytes": 25742483, + "redis_bytes": 30986336, + "search_p50_ns": 2208, + "search_p95_ns": 3416, + "search_p99_ns": 13583, + "search_samples": 455, + "sent_bytes": 684299 + }, + { + "commit_ms": 5.154, + "commit_to_ready_ms": 510.031, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 621674496, + "n": 1000000, + "operation": "add_1_repeat_0", + "ready_ms": 515.185, + "received_bytes": 1410960, + "redis_bytes": 31764816, + "search_p50_ns": 2292, + "search_p95_ns": 4209, + "search_p99_ns": 10417, + "search_samples": 503, + "sent_bytes": 710338 + }, + { + "commit_ms": 7.468, + "commit_to_ready_ms": 520.129, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 721731584, + "n": 1000000, + "operation": "remove_1_repeat_0", + "ready_ms": 527.598, + "received_bytes": 1410965, + "redis_bytes": 32470240, + "search_p50_ns": 2291, + "search_p95_ns": 9000, + "search_p99_ns": 17792, + "search_samples": 519, + "sent_bytes": 710320 + }, + { + "commit_ms": 11.262, + "commit_to_ready_ms": 750.079, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 731529216, + "n": 1000000, + "operation": "add_1_repeat_1", + "ready_ms": 761.342, + "received_bytes": 1409714, + "redis_bytes": 33182272, + "search_p50_ns": 3667, + "search_p95_ns": 15083, + "search_p99_ns": 21125, + "search_samples": 725, + "sent_bytes": 709713 + }, + { + "commit_ms": 7.18, + "commit_to_ready_ms": 520.085, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 766279680, + "n": 1000000, + "operation": "remove_1_repeat_1", + "ready_ms": 527.265, + "received_bytes": 1409709, + "redis_bytes": 33887680, + "search_p50_ns": 2250, + "search_p95_ns": 4000, + "search_p99_ns": 17041, + "search_samples": 500, + "sent_bytes": 709695 + }, + { + "commit_ms": 7.578, + "commit_to_ready_ms": 510.083, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 767836160, + "n": 1000000, + "operation": "add_1_repeat_2", + "ready_ms": 517.662, + "received_bytes": 1411358, + "redis_bytes": 34600608, + "search_p50_ns": 2208, + "search_p95_ns": 3666, + "search_p99_ns": 8209, + "search_samples": 506, + "sent_bytes": 710538 + }, + { + "commit_ms": 8.405, + "commit_to_ready_ms": 670.088, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 767918080, + "n": 1000000, + "operation": "remove_1_repeat_2", + "ready_ms": 678.493, + "received_bytes": 1411359, + "redis_bytes": 35306112, + "search_p50_ns": 2459, + "search_p95_ns": 14625, + "search_p99_ns": 18000, + "search_samples": 650, + "sent_bytes": 710520 + }, + { + "commit_ms": 9.462, + "commit_to_ready_ms": 510.155, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 830423040, + "n": 1000000, + "operation": "add_1", + "ready_ms": 519.617, + "received_bytes": 1410360, + "redis_bytes": 36019152, + "search_p50_ns": 2209, + "search_p95_ns": 4542, + "search_p99_ns": 10166, + "search_samples": 488, + "sent_bytes": 710040 + }, + { + "commit_ms": 8.794, + "commit_to_ready_ms": 520.197, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 830914560, + "n": 1000000, + "operation": "remove_1", + "ready_ms": 528.992, + "received_bytes": 1410364, + "redis_bytes": 36717424, + "search_p50_ns": 2292, + "search_p95_ns": 4333, + "search_p99_ns": 11208, + "search_samples": 505, + "sent_bytes": 710022 + }, + { + "commit_ms": 126.475, + "commit_to_ready_ms": 560.083, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 830947328, + "n": 1000000, + "operation": "add_1000", + "ready_ms": 686.558, + "received_bytes": 12312448, + "redis_bytes": 43629584, + "search_p50_ns": 2209, + "search_p95_ns": 3625, + "search_p99_ns": 10083, + "search_samples": 662, + "sent_bytes": 7319581 + }, + { + "commit_ms": 127.119, + "commit_to_ready_ms": 610.034, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 831045632, + "n": 1000000, + "operation": "remove_1000", + "ready_ms": 737.153, + "received_bytes": 12312454, + "redis_bytes": 44331504, + "search_p50_ns": 2375, + "search_p95_ns": 11584, + "search_p99_ns": 16000, + "search_samples": 706, + "sent_bytes": 7296581 + }, + { + "commit_ms": 584.509, + "commit_to_ready_ms": 830.086, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 831700992, + "n": 1000000, + "operation": "add_10000", + "ready_ms": 1414.596, + "received_bytes": 47386880, + "redis_bytes": 71431408, + "search_p50_ns": 2458, + "search_p95_ns": 12625, + "search_p99_ns": 20000, + "search_samples": 1370, + "sent_bytes": 28641089 + }, + { + "commit_ms": 472.359, + "commit_to_ready_ms": 790.07, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 884228096, + "n": 1000000, + "operation": "remove_10000", + "ready_ms": 1262.43, + "received_bytes": 47386742, + "redis_bytes": 72113376, + "search_p50_ns": 2292, + "search_p95_ns": 3375, + "search_p99_ns": 9959, + "search_samples": 1227, + "sent_bytes": 28400887 + }, + { + "commit_ms": 640.398, + "commit_to_ready_ms": 1170.074, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 1374404608, + "n": 1000000, + "operation": "full_replace", + "ready_ms": 1810.473, + "received_bytes": 53497106, + "redis_bytes": 103219120, + "search_p50_ns": 2334, + "search_p95_ns": 12750, + "search_p99_ns": 19333, + "search_samples": 1747, + "sent_bytes": 33036863 + } + ], + "startup_ms": 769.664, + "prune": { + "ms": 45.511, + "generations": 14, + "chunks": 8729, + "redis_bytes": 33018160 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=1000000 kind=shared seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469780686204 uptime_in_seconds:69 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084884 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 1000000, + "kind": "shared", + "repeat": 2, + "measurements": [ + { + "commit_ms": 396.096, + "commit_to_ready_ms": 820.122, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 408158208, + "n": 1000000, + "operation": "initial_load", + "ready_ms": 1216.219, + "received_bytes": 25923454, + "redis_bytes": 30982224, + "search_p50_ns": 375, + "search_p95_ns": 1625, + "search_p99_ns": 6083, + "search_samples": 1175, + "sent_bytes": 30356458 + }, + { + "commit_ms": 505.407, + "commit_to_ready_ms": 0.017, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 487129088, + "n": 1000000, + "operation": "identical_replace", + "ready_ms": 505.425, + "received_bytes": 25742571, + "redis_bytes": 30989856, + "search_p50_ns": 2250, + "search_p95_ns": 9250, + "search_p99_ns": 16417, + "search_samples": 483, + "sent_bytes": 684400 + }, + { + "commit_ms": 5.433, + "commit_to_ready_ms": 540.066, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 668450816, + "n": 1000000, + "operation": "add_1_repeat_0", + "ready_ms": 545.5, + "received_bytes": 1410976, + "redis_bytes": 31768368, + "search_p50_ns": 2250, + "search_p95_ns": 4708, + "search_p99_ns": 13417, + "search_samples": 522, + "sent_bytes": 710338 + }, + { + "commit_ms": 7.703, + "commit_to_ready_ms": 510.189, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 690077696, + "n": 1000000, + "operation": "remove_1_repeat_0", + "ready_ms": 517.892, + "received_bytes": 1410981, + "redis_bytes": 32473792, + "search_p50_ns": 2333, + "search_p95_ns": 4625, + "search_p99_ns": 14584, + "search_samples": 485, + "sent_bytes": 710320 + }, + { + "commit_ms": 9.282, + "commit_to_ready_ms": 520.125, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 845266944, + "n": 1000000, + "operation": "add_1_repeat_1", + "ready_ms": 529.408, + "received_bytes": 1409730, + "redis_bytes": 33185712, + "search_p50_ns": 2208, + "search_p95_ns": 4250, + "search_p99_ns": 12167, + "search_samples": 496, + "sent_bytes": 709713 + }, + { + "commit_ms": 7.416, + "commit_to_ready_ms": 550.109, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 899596288, + "n": 1000000, + "operation": "remove_1_repeat_1", + "ready_ms": 557.525, + "received_bytes": 1409728, + "redis_bytes": 33891184, + "search_p50_ns": 2333, + "search_p95_ns": 4583, + "search_p99_ns": 13125, + "search_samples": 526, + "sent_bytes": 709695 + }, + { + "commit_ms": 8.618, + "commit_to_ready_ms": 550.16, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 899596288, + "n": 1000000, + "operation": "add_1_repeat_2", + "ready_ms": 558.779, + "received_bytes": 1411375, + "redis_bytes": 34583712, + "search_p50_ns": 2208, + "search_p95_ns": 4375, + "search_p99_ns": 12417, + "search_samples": 545, + "sent_bytes": 710538 + }, + { + "commit_ms": 8.379, + "commit_to_ready_ms": 570.108, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 899596288, + "n": 1000000, + "operation": "remove_1_repeat_2", + "ready_ms": 578.487, + "received_bytes": 1411375, + "redis_bytes": 35289168, + "search_p50_ns": 2333, + "search_p95_ns": 5791, + "search_p99_ns": 12833, + "search_samples": 565, + "sent_bytes": 710520 + }, + { + "commit_ms": 8.811, + "commit_to_ready_ms": 500.067, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 899596288, + "n": 1000000, + "operation": "add_1", + "ready_ms": 508.878, + "received_bytes": 1410379, + "redis_bytes": 35995056, + "search_p50_ns": 2292, + "search_p95_ns": 3834, + "search_p99_ns": 10459, + "search_samples": 495, + "sent_bytes": 710040 + }, + { + "commit_ms": 9.252, + "commit_to_ready_ms": 540.092, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 899612672, + "n": 1000000, + "operation": "remove_1", + "ready_ms": 549.345, + "received_bytes": 1410380, + "redis_bytes": 36693264, + "search_p50_ns": 2375, + "search_p95_ns": 7792, + "search_p99_ns": 12209, + "search_samples": 536, + "sent_bytes": 710022 + }, + { + "commit_ms": 125.588, + "commit_to_ready_ms": 590.097, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 899645440, + "n": 1000000, + "operation": "add_1000", + "ready_ms": 715.686, + "received_bytes": 12312538, + "redis_bytes": 43627312, + "search_p50_ns": 2208, + "search_p95_ns": 3625, + "search_p99_ns": 10916, + "search_samples": 685, + "sent_bytes": 7319682 + }, + { + "commit_ms": 122.89, + "commit_to_ready_ms": 610.06, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 899678208, + "n": 1000000, + "operation": "remove_1000", + "ready_ms": 732.95, + "received_bytes": 12312470, + "redis_bytes": 44331296, + "search_p50_ns": 2333, + "search_p95_ns": 3791, + "search_p99_ns": 12917, + "search_samples": 720, + "sent_bytes": 7296581 + }, + { + "commit_ms": 493.146, + "commit_to_ready_ms": 1030.042, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 901103616, + "n": 1000000, + "operation": "add_10000", + "ready_ms": 1523.188, + "received_bytes": 47386824, + "redis_bytes": 71432864, + "search_p50_ns": 2458, + "search_p95_ns": 11708, + "search_p99_ns": 16667, + "search_samples": 1484, + "sent_bytes": 28640988 + }, + { + "commit_ms": 487.746, + "commit_to_ready_ms": 760.118, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 902610944, + "n": 1000000, + "operation": "remove_10000", + "ready_ms": 1247.864, + "received_bytes": 47386754, + "redis_bytes": 72114800, + "search_p50_ns": 2209, + "search_p95_ns": 3709, + "search_p99_ns": 11417, + "search_samples": 1203, + "sent_bytes": 28400887 + }, + { + "commit_ms": 642.797, + "commit_to_ready_ms": 1000.136, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 1192738816, + "n": 1000000, + "operation": "full_replace", + "ready_ms": 1642.934, + "received_bytes": 53497118, + "redis_bytes": 103213488, + "search_p50_ns": 2250, + "search_p95_ns": 4208, + "search_p99_ns": 11542, + "search_samples": 1576, + "sent_bytes": 33036863 + } + ], + "startup_ms": 774.471, + "prune": { + "ms": 53.015, + "generations": 14, + "chunks": 8729, + "redis_bytes": 33012608 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=1000000 kind=shared seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469848710968 uptime_in_seconds:137 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11084952 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + }, + { + "backend": "redis", + "n": 1000000, + "kind": "shared", + "repeat": 3, + "measurements": [ + { + "commit_ms": 383.307, + "commit_to_ready_ms": 810.053, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 420151296, + "n": 1000000, + "operation": "initial_load", + "ready_ms": 1193.36, + "received_bytes": 25923458, + "redis_bytes": 30987344, + "search_p50_ns": 417, + "search_p95_ns": 1875, + "search_p99_ns": 10250, + "search_samples": 1166, + "sent_bytes": 30356458 + }, + { + "commit_ms": 458.034, + "commit_to_ready_ms": 0.018, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 496189440, + "n": 1000000, + "operation": "identical_replace", + "ready_ms": 458.053, + "received_bytes": 25742577, + "redis_bytes": 30994992, + "search_p50_ns": 2250, + "search_p95_ns": 3458, + "search_p99_ns": 11417, + "search_samples": 436, + "sent_bytes": 684400 + }, + { + "commit_ms": 5.112, + "commit_to_ready_ms": 540.101, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 652034048, + "n": 1000000, + "operation": "add_1_repeat_0", + "ready_ms": 545.213, + "received_bytes": 1410982, + "redis_bytes": 31773456, + "search_p50_ns": 2167, + "search_p95_ns": 4917, + "search_p99_ns": 13666, + "search_samples": 514, + "sent_bytes": 710338 + }, + { + "commit_ms": 8.148, + "commit_to_ready_ms": 510.098, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 719814656, + "n": 1000000, + "operation": "remove_1_repeat_0", + "ready_ms": 518.247, + "received_bytes": 1410986, + "redis_bytes": 32478896, + "search_p50_ns": 2167, + "search_p95_ns": 4459, + "search_p99_ns": 10708, + "search_samples": 495, + "sent_bytes": 710320 + }, + { + "commit_ms": 9.121, + "commit_to_ready_ms": 520.109, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 746192896, + "n": 1000000, + "operation": "add_1_repeat_1", + "ready_ms": 529.231, + "received_bytes": 1409735, + "redis_bytes": 33190912, + "search_p50_ns": 2250, + "search_p95_ns": 6583, + "search_p99_ns": 13708, + "search_samples": 520, + "sent_bytes": 709713 + }, + { + "commit_ms": 7.31, + "commit_to_ready_ms": 520.107, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 808730624, + "n": 1000000, + "operation": "remove_1_repeat_1", + "ready_ms": 527.417, + "received_bytes": 1409734, + "redis_bytes": 33896320, + "search_p50_ns": 2375, + "search_p95_ns": 5000, + "search_p99_ns": 10833, + "search_samples": 504, + "sent_bytes": 709695 + }, + { + "commit_ms": 9.206, + "commit_to_ready_ms": 520.105, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 808763392, + "n": 1000000, + "operation": "add_1_repeat_2", + "ready_ms": 529.312, + "received_bytes": 1411381, + "redis_bytes": 34588752, + "search_p50_ns": 2250, + "search_p95_ns": 6542, + "search_p99_ns": 11709, + "search_samples": 521, + "sent_bytes": 710538 + }, + { + "commit_ms": 9.299, + "commit_to_ready_ms": 520.115, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 808763392, + "n": 1000000, + "operation": "remove_1_repeat_2", + "ready_ms": 529.414, + "received_bytes": 1411382, + "redis_bytes": 35294224, + "search_p50_ns": 2250, + "search_p95_ns": 4458, + "search_p99_ns": 13541, + "search_samples": 502, + "sent_bytes": 710520 + }, + { + "commit_ms": 9.044, + "commit_to_ready_ms": 520.138, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 820953088, + "n": 1000000, + "operation": "add_1", + "ready_ms": 529.183, + "received_bytes": 1410383, + "redis_bytes": 36000112, + "search_p50_ns": 2292, + "search_p95_ns": 3583, + "search_p99_ns": 10209, + "search_samples": 520, + "sent_bytes": 710040 + }, + { + "commit_ms": 8.908, + "commit_to_ready_ms": 520.269, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 820953088, + "n": 1000000, + "operation": "remove_1", + "ready_ms": 529.178, + "received_bytes": 1410386, + "redis_bytes": 36705568, + "search_p50_ns": 2208, + "search_p95_ns": 4041, + "search_p99_ns": 10167, + "search_samples": 505, + "sent_bytes": 710022 + }, + { + "commit_ms": 128.433, + "commit_to_ready_ms": 600.073, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 822034432, + "n": 1000000, + "operation": "add_1000", + "ready_ms": 728.507, + "received_bytes": 12312471, + "redis_bytes": 43632000, + "search_p50_ns": 2125, + "search_p95_ns": 3792, + "search_p99_ns": 10834, + "search_samples": 698, + "sent_bytes": 7319581 + }, + { + "commit_ms": 130.669, + "commit_to_ready_ms": 590.112, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 822050816, + "n": 1000000, + "operation": "remove_1000", + "ready_ms": 720.782, + "received_bytes": 12312547, + "redis_bytes": 44341104, + "search_p50_ns": 2292, + "search_p95_ns": 4167, + "search_p99_ns": 10750, + "search_samples": 687, + "sent_bytes": 7296682 + }, + { + "commit_ms": 493.813, + "commit_to_ready_ms": 760.094, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 822329344, + "n": 1000000, + "operation": "add_10000", + "ready_ms": 1253.907, + "received_bytes": 47386757, + "redis_bytes": 71439776, + "search_p50_ns": 2167, + "search_p95_ns": 3208, + "search_p99_ns": 11417, + "search_samples": 1221, + "sent_bytes": 28640887 + }, + { + "commit_ms": 491.342, + "commit_to_ready_ms": 760.064, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 857587712, + "n": 1000000, + "operation": "remove_10000", + "ready_ms": 1251.407, + "received_bytes": 47386760, + "redis_bytes": 72128880, + "search_p50_ns": 2333, + "search_p95_ns": 3125, + "search_p99_ns": 9250, + "search_samples": 1209, + "sent_bytes": 28400887 + }, + { + "commit_ms": 642.836, + "commit_to_ready_ms": 960.101, + "delta_search": false, + "kind": "shared", + "max_rss_bytes": 1178599424, + "n": 1000000, + "operation": "full_replace", + "ready_ms": 1602.937, + "received_bytes": 53497124, + "redis_bytes": 103219840, + "search_p50_ns": 2167, + "search_p95_ns": 3375, + "search_p99_ns": 10208, + "search_samples": 1553, + "sent_bytes": 33036863 + } + ], + "startup_ms": 775.458, + "prune": { + "ms": 54.206, + "generations": 14, + "chunks": 8729, + "redis_bytes": 33017824 + }, + "environment": "go=go1.26.7 os=darwin arch=arm64 cpus=10 n=1000000 kind=shared seed=20260906 server=# Server redis_version:8.10.1 redis_git_sha1:00000000 redis_git_dirty:1 redis_build_id:81870544b30d700a redis_mode:standalone os:Darwin 25.6.0 arm64 arch_bits:64 monotonic_clock:ARM CNTVCT @ 1000 ticks/us multiplexing_api:kqueue atomicvar_api:c11-builtin gcc_version:4.2.1 process_id:44773 process_supervised:no run_id:dd759bdd3297b5a215debf16e9f1828fcd7df1c1 tcp_port:6379 server_time_usec:1789469913736726 uptime_in_seconds:202 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:11085017 executable:/opt/homebrew/opt/redis/bin/redis-server config_file:/opt/homebrew/etc/redis.conf io_threads_active:0 listener0:name=tcp,bind=127.0.0.1,bind=::1,port=6379 ", + "passed": true + } + ], + "million_safety": { + "passed": true, + "output": "=== RUN TestVersionedMillionSafety\n--- PASS: TestVersionedMillionSafety (2.33s)\nPASS" + } +} diff --git a/docs/content/reference/_index.md b/docs/content/reference/_index.md index 428fb0f..d01c394 100644 --- a/docs/content/reference/_index.md +++ b/docs/content/reference/_index.md @@ -17,4 +17,5 @@ weight: 3 - [Benchmarks](benchmarks/) — round trips and timings, with the commands that produce them - [V3 performance report](versioned-performance/) — the archived R1 million-keyword baseline - [R2/R3 verification](r2-r3-performance/) — incremental download, engine memory, bounded APIs +- [V3 single-engine benchmark](v3-single-engine-20260915/) — current Redis measurements after overlay removal - [V3 delta-search dashboard](versioned-delta-dashboard/) — final Redis/Valkey p95 and release-gate results diff --git a/docs/content/reference/v3-single-engine-20260915.md b/docs/content/reference/v3-single-engine-20260915.md new file mode 100644 index 0000000..03efccd --- /dev/null +++ b/docs/content/reference/v3-single-engine-20260915.md @@ -0,0 +1,51 @@ +--- +title: "V3 single-engine benchmark — 2026-09-15" +description: "Redis measurements for the V3 single-engine path at up to one million keywords." +--- + +# V3 single-engine benchmark — 2026-09-15 + +This report measures the V3 single-engine path after removing the experimental +two-automaton overlay. It ran against Redis at `127.0.0.1:6379` using commit +`212179f`, with three fresh Go processes per size and distribution. + +## Environment + +- Apple M4, 10 logical CPUs, macOS Darwin 25.6.0, arm64 +- Go 1.26.7; Redis 8.10.1; standalone localhost TCP +- MemoryEfficient preset, 50 ms polling, default five-minute leases +- Sizes: 10,000, 100,000, and 1,000,000 keywords +- Distributions: shared prefix, diverse prefix, and Korean +- Seed: `20260906` +- All 27 scale runs and the million-keyword safety scenario passed + +These are developer-workstation measurements, not production latency or memory +guarantees. Redis memory and network counters are server-wide. Prune advances +generation timestamps past the retention horizon instead of waiting 24 hours. +Valkey was not measured in this run. + +## Million-keyword results + +Values are min–max across three runs, with the median in parentheses. RSS is the +process high-water mark; search p95 is sampled during the update. + +| Distribution | Initial ready (s) | Startup (s) | Add 1 ready (s) | Full replace ready (s) | Peak RSS (GiB) | Add 1 search p95 (µs) | Redis after prune (MiB) | +|---|---:|---:|---:|---:|---:|---:|---:| +| Shared | 1.193–1.216 (1.198) | 0.770–0.775 (0.774) | 0.509–0.529 (0.520) | 1.603–1.810 (1.643) | 1.098–1.280 (1.111) | 3.583–4.542 (3.834) | 31.483–31.489 (31.488) | +| Diverse | 1.639–1.728 (1.708) | 1.112–1.336 (1.262) | 0.878–0.917 (0.879) | 1.943–2.217 (2.099) | 2.199–2.444 (2.395) | 4.000–6.083 (4.166) | 23.157–23.171 (23.164) | +| Korean | 2.082–2.173 (2.112) | 1.343–1.530 (1.437) | 1.007–1.179 (1.019) | 2.578–2.805 (2.740) | 2.855–3.058 (2.961) | 4.583–12.834 (4.708) | 43.934–43.947 (43.941) | + +The raw machine-readable result is +[`v3-20260915-redis.json`](../../../benchmarks/results/v3-20260915-redis.json). + +## Reproduce + +```sh +ACOR_V3_SCALE_ADDR=127.0.0.1:6379 \ +ACOR_V3_SCALE_OUTPUT=/tmp/acor-v3-20260915-redis \ +ACOR_V3_SCALE_REPEATS=3 \ + make bench-v3 +``` + +The benchmark uses disposable collection names, does not run `FLUSHDB`, and +includes the million-keyword safety and pruning scenario. diff --git a/docs/content/reference/versioned-delta-validation.md b/docs/content/reference/versioned-delta-validation.md index 95b52a0..194428f 100644 --- a/docs/content/reference/versioned-delta-validation.md +++ b/docs/content/reference/versioned-delta-validation.md @@ -1,98 +1,34 @@ --- -title: "V3 delta-search validation" -description: "Opt-in delta search: parity, release gates, and reproducible Redis/Valkey measurements." +title: "V3 delta-search validation archive" +description: "Archived measurements for the retired V3 delta-search experiment." --- -# V3 delta-search validation +# V3 delta-search validation archive -`VersionedOptions.DeltaSearch` remains opt-in. This report evaluates the small-update -search view against the existing full rebuild path; it does not change the V3 storage -format or the default search behavior. +This page preserves the Redis and Valkey measurements from the retired +`VersionedOptions.DeltaSearch` experiment. The experiment used a base automaton +plus an additions automaton and deletion set for small updates, but its release +gate failed: search p95 reached 2.62 times the full-rebuild baseline and Korean +peak RSS reached 1.55 times the baseline. -## Release gate +V3 now serves one immutable engine for every version. `DeltaSearch` remains in +the public option type for source compatibility, but it has no effect, and +`DeltaSearch`/`DeltaKeywords` report false/zero in `VersionedStatus`. -For each server and each million-keyword distribution (shared prefix, diverse prefix, -and Korean), run the baseline and delta modes in three independent processes. Compare -medians for additions and removals of one and 128 keywords: +The archived raw results remain in +[`benchmarks/results/v3-delta-20260914-redis.json`](https://github.com/skyoo2003/acor/blob/main/benchmarks/results/v3-delta-20260914-redis.json) +and +[`benchmarks/results/v3-delta-20260914-valkey.json`](https://github.com/skyoo2003/acor/blob/main/benchmarks/results/v3-delta-20260914-valkey.json). +They are historical workstation measurements, not current release gates. -| Metric | Required delta result | -|---|---| -| `WaitForVersion` ready time | At most 30% of full-rebuild baseline | -| Steady search p95 after readiness | At most 110% of baseline | -| Process peak RSS after compaction | No greater than baseline | - -Correctness is mandatory even if the timing gates pass. Changes of 129 keywords must -fall back to a full rebuild. Every search API must agree with a fully rebuilt engine -while the overlay is active and after compaction. Failed compaction must retain the -already serving version and report the error. A missed gate keeps the option off by -default and is reported rather than hidden by an aggregate across servers. - -## Measurement method - -`scripts/benchmark-v3.sh` runs `TestVersionedDeltaScale` when -`ACOR_V3_DELTA_COMPARE=1`. It starts a fresh Go process per mode, distribution, and -repetition against a disposable real server, and cleans up only its uniquely named -collection keys. The test uses the fixed seed 20260906 and MemoryEfficient preset, -with a 50 ms polling interval. It loads one million entries, measures add/remove 1, -add/remove 128, add/remove 129, then measures search during idle compaction. The -ready interval includes the Redis write and `WaitForVersion`; the search p95 is sampled -for 500 ms immediately after readiness using the same short query in both modes. -The RSS field is the process high-water mark at each sample, not an isolated allocation -count for that phase. The final RSS comparison includes compaction. `heap_alloc` is a -point-in-time Go heap observation. Search timing is local and excludes Redis I/O. - -The current evaluator also records p95 separately for `Find`, `FindSet`, -`FindIndex`, `FindMatches`, `Contains`, `FindStream`, `FindBatch`, -`FindParallel`, `FindIndexParallel`, `Scan`, `MaskText`, and `ReplaceText`. -Each mode uses identical text for added-keyword, removed-keyword, and -delta-miss cases. The removed-base case actually deletes a word from the -million-word base. Parallel calls use 2 workers, 128-rune chunks, and text -long enough to create multiple chunks. The p95 of each API/input pair must be -at most 1.10 times its full-rebuild counterpart. The evaluator records RSS -after the 129-keyword full rebuild and again after idle compaction; the -process-wide high-water mark after compaction is the RSS gate. Runs from the -older format, without `search_apis`, cannot satisfy the current evaluator. - -The R1/R2 reports used a development workstation with persistence disabled. This -comparison should use the same host, Go version, Redis 8.10.1, and Valkey 9.1.2 with -`prefetch-batch-max-size 0`, running one server workload at a time. The Valkey source -archive SHA-256 is recorded in the [R1 report](../versioned-performance/). +For current V3 measurements, run the single-engine scale benchmark: ```sh ACOR_V3_SCALE_ADDR=127.0.0.1:6379 \ -ACOR_V3_DELTA_COMPARE=1 \ -ACOR_V3_SCALE_COUNTS=1000000 \ -ACOR_V3_SCALE_MODES='baseline delta' \ -ACOR_V3_SCALE_REPEATS=3 \ -ACOR_V3_SCALE_OUTPUT=/tmp/acor-v3-delta-redis \ +ACOR_V3_SCALE_OUTPUT=/tmp/acor-v3-scale \ +ACOR_V3_SCALE_REPEATS=2 \ make bench-v3 -python3 scripts/evaluate-v3-delta.py /tmp/acor-v3-delta-redis ``` -Run the same command with a separate output directory against Valkey. The evaluator -exits nonzero if a log is missing, a run failed, or any numerical gate fails. It does -not combine Redis and Valkey results into one passing average. - -## Final results (2026-09-14) - -The final matrix ran on macOS/Darwin 25.6.0, arm64, 10 logical CPUs, Go -1.26.7, Redis 8.10.1, and source-built Valkey 9.1.2. Both servers used -localhost with persistence disabled; Valkey used `prefetch-batch-max-size 0`. -Three independent processes per mode and distribution produced the medians in -[`v3-delta-20260914-redis.json`](https://github.com/skyoo2003/acor/blob/main/benchmarks/results/v3-delta-20260914-redis.json) -and [`v3-delta-20260914-valkey.json`](https://github.com/skyoo2003/acor/blob/main/benchmarks/results/v3-delta-20260914-valkey.json). -The [results dashboard](../versioned-delta-dashboard/) shows every server and -distribution, plus the API-level p95 failures. - -| Server | Search p95 failures (of 555) | Worst p95 ratio (≤1.10) | Worst ready ratio (≤0.30) | Korean peak RSS ratio (≤1.00) | -|---|---:|---:|---:|---:| -| Redis | 202 | 2.61 | 0.164 | 1.552 | -| Valkey | 208 | 2.62 | 0.164 | 1.527 | - -All 30 ready-time checks passed, but 410 of 1,110 search p95 comparisons -failed. The Korean peak-RSS check failed on both servers. No API sample -overlapped a compaction build. Peak RSS is a process high-water mark, so the -comparison does not isolate an individual allocation. These workstation -measurements do not establish production latency or memory guarantees. - -The release gate **fails**. `DeltaSearch` remains opt-in. +The benchmark uses disposable collection names, does not run `FLUSHDB`, and +includes the million-keyword safety and pruning scenario. diff --git a/docs/content/reference/versioned.md b/docs/content/reference/versioned.md index 72a3387..842b828 100644 --- a/docs/content/reference/versioned.md +++ b/docs/content/reference/versioned.md @@ -82,19 +82,12 @@ A successful write means the Redis commit landed. The calling instance and every instance may still be searching the previous engine. `WaitForVersion` waits for that commit or a later one and honors cancellation. `Status` exposes the observed active version, the serving version, build start and duration, and the most recent error. -`DeltaSearch` and `DeltaKeywords` report whether the serving version uses a small -change set and how many additions and deletions it contains. - -Set `VersionedOptions.DeltaSearch` to enable the experimental small-update path for -`MemoryEfficient`. Changes of at most 128 keywords download only changed buckets and -publish a base automaton plus an additions automaton and deletion set. `WaitForVersion` -completes when this search view is ready. After one second without another change, a -background build replaces it with a full automaton; later changes or build failures -leave the published search view intact. Larger changes and other presets continue to -use the full rebuild path. This option remains off by default pending million-keyword -Redis and Valkey latency, search p95, and peak RSS validation. The -[delta-search validation report](../versioned-delta-validation/) records the -release gate and measurements against the full rebuild path. +`DeltaSearch` and `DeltaKeywords` remain in the status and option types for source +compatibility. V3 currently serves one immutable engine for every version, regardless +of `VersionedOptions.DeltaSearch`; both fields report false and zero. This avoids the +experimental two-automaton search path, whose million-keyword measurements showed +search p95 and peak RSS regressions. The historical [delta-search validation report](../versioned-delta-validation/) +records those measurements. | Refresh behavior | | |---|---| diff --git a/internal/engine/engine_bloom.go b/internal/engine/engine_bloom.go index e35f688..0268c52 100644 --- a/internal/engine/engine_bloom.go +++ b/internal/engine/engine_bloom.go @@ -66,12 +66,6 @@ func (bf *bloomFilter) memoryBytes() int64 { return int64(len(bf.bits)) * 8 } -// skipAtRoot reports whether ch can be skipped: it cannot start any keyword and -// traversal is at the root state. A nil filter never skips (pre-filter disabled). -func (bf *bloomFilter) skipAtRoot(atRoot bool, r rune) bool { - return bf != nil && atRoot && !bf.mightContain(r) -} - func (bf *bloomFilter) hashPair(r rune) (hash1, hash2 uint64) { //nolint:gosec var h1 uint64 = 14695981039346656037 h1 ^= uint64(r) //nolint:gosec diff --git a/internal/engine/overlay.go b/internal/engine/overlay.go deleted file mode 100644 index af28175..0000000 --- a/internal/engine/overlay.go +++ /dev/null @@ -1,582 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package engine - -import ( - "slices" - "strings" - "unicode/utf8" -) - -// Overlay combines an immutable base with a small replacement set. Its inputs -// must not be mutated after construction. It is used only by V3 snapshots. -func Overlay(base, added *Engine, removed map[string]struct{}) *Engine { - if added.MaxKeywordRunes() == 0 && len(removed) == 0 { - return base - } - i := &overlayEngine{base: base, added: added, removed: removed} - if _, ok := base.impl.(*memEfficientEngine); ok { - if a, ok := added.impl.(*memEfficientEngine); ok { - i.literal = newLiteralDelta(&a.trie.out) - } - } - return &Engine{preset: base.preset, impl: i, maxKeywordRunes: max(base.MaxKeywordRunes(), added.MaxKeywordRunes())} -} - -type overlayEngine struct { - base, added *Engine - removed map[string]struct{} - literal *literalDelta -} - -// literalDelta confines a small ASCII addition set to occurrences of its -// common prefix. A map lookup per distinct byte length verifies the complete -// word, so a 128-word batch with one prefix costs one lookup at each candidate. -// The general two-automaton path remains available for other dictionaries. -type literalDelta struct { - prefix string - lengths []int - words map[int]map[string]string -} - -// Candidate collection is bounded to short strings; long strings use the -// streaming automata so match-dense input cannot retain one hit per occurrence. -const literalQueryLimit = 4096 - -type literalHit struct { - endByte int - length int - keyword string -} - -func newLiteralDelta(out *outputs) *literalDelta { - if out.keywordCount() == 0 || out.keywordCount() > 128 { - return nil - } - var prefix string - groups := make(map[int]map[string]string) - for _, word := range out.keywords[1:] { - for i := range len(word) { - if word[i] >= utf8.RuneSelf { - return nil - } - } - if prefix == "" { - prefix = word - } else { - i := 0 - for i < len(prefix) && i < len(word) && prefix[i] == word[i] { - i++ - } - prefix = prefix[:i] - } - if groups[len(word)] == nil { - groups[len(word)] = make(map[string]string) - } - groups[len(word)][word] = word - } - if len(prefix) < 3 || len(groups) > 8 { - return nil - } - lengths := make([]int, 0, len(groups)) - for length := range groups { - lengths = append(lengths, length) - } - slices.Sort(lengths) - return &literalDelta{prefix: prefix, lengths: lengths, words: groups} -} - -func (d *literalDelta) matches(text string, hits []literalHit) []literalHit { - for offset := 0; offset < len(text); { - at := strings.Index(text[offset:], d.prefix) - if at < 0 { - break - } - at += offset - for _, length := range d.lengths { - if at+length <= len(text) { - word := text[at : at+length] - if canonical, ok := d.words[length][word]; ok { - hits = append(hits, literalHit{endByte: at + length, length: length, keyword: canonical}) - } - } - } - offset = at + 1 - } - if len(hits) > 1 { - slices.SortFunc(hits, func(a, b literalHit) int { - if a.endByte != b.endByte { - return a.endByte - b.endByte - } - return b.length - a.length - }) - } - return hits -} - -type overlayMatch struct { - keyword string - start int - end int - source int - order int -} - -func (o *overlayEngine) buildFromKeywords(map[string]struct{}) { panic("engine: immutable overlay") } - -func (o *overlayEngine) matchString(text string, emit func(string, int, int) bool) { - if o.literal != nil && len(text) <= literalQueryLimit { - o.matchStringLiteral(text, emit) - return - } - base, baseOK := o.base.impl.(*memEfficientEngine) - added, addedOK := o.added.impl.(*memEfficientEngine) - if !baseOK || !addedOK { - i := 0 - o.matchStreamWindow(func() (rune, bool) { - if i == len(text) { - return 0, false - } - r, size := utf8.DecodeRuneInString(text[i:]) - i += size - return r, true - }, emit) - return - } - if added.trie.out.keywordCount() == 0 { - o.base.MatchString(text, func(k string, start, end int) bool { - if _, removed := o.removed[k]; removed { - return true - } - return emit(k, start, end) - }) - return - } - baseState, addedState, end := 0, 0, 0 - for _, ch := range text { - end++ - baseState = base.advance(baseState, ch) - addedState = added.advance(addedState, ch) - if base.trie.out.own[baseState] == 0 && base.trie.out.outLink[baseState] == outNone && - added.trie.out.own[addedState] == 0 && added.trie.out.outLink[addedState] == outNone { - continue - } - if !o.emitMerged(&base.trie.out, baseState, &added.trie.out, addedState, end, emit) { - return - } - } -} - -// matchStringLiteral traverses the large base only once. The addition matcher -// inspects only complete literal candidates at occurrences of its common -// prefix, then merges those matches with base outputs at the same rune end. -// -//nolint:gocyclo // The hot scan keeps transitions and ordered output merge in one loop. -func (o *overlayEngine) matchStringLiteral(text string, emit func(string, int, int) bool) { - var hitBuffer [8]literalHit - hits := o.literal.matches(text, hitBuffer[:0]) - if len(hits) == 0 { - if len(o.removed) == 0 { - o.base.MatchString(text, emit) - return - } - o.base.MatchString(text, func(k string, start, end int) bool { - if _, removed := o.removed[k]; removed { - return true - } - return emit(k, start, end) - }) - return - } - base := o.base.impl.(*memEfficientEngine) - out := &base.trie.out - state, end, hitIndex := 0, 0, 0 - for pos, ch := range text { - end++ - if !base.bloom.skipAtRoot(state == 0, ch) { - for { - if next, ok := base.trie.nodes[state].next(ch); ok { - state = next - break - } - if state == 0 { - break - } - state = base.trie.nodes[state].fail - } - } - // Literal additions are ASCII, so their last rune occupies one byte. - endByte := pos + 1 - baseState := nextOutput(out, state) - for baseState != outNone || hitIndex < len(hits) && hits[hitIndex].endByte == endByte { - baseID := int32(0) - if baseState != outNone { - baseID = out.own[baseState] - } - if hitIndex == len(hits) || hits[hitIndex].endByte != endByte || - baseID != 0 && int(out.runeLens[baseID]) >= hits[hitIndex].length { - keyword := out.keywords[baseID] - baseState = nextOutput(out, int(out.outLink[baseState])) - if _, removed := o.removed[keyword]; !removed && !emit(keyword, end-int(out.runeLens[baseID]), end) { - return - } - } else { - hit := hits[hitIndex] - hitIndex++ - if !emit(hit.keyword, end-hit.length, end) { - return - } - } - } - } -} - -// emitMerged walks each output chain once. Chains follow failure links from -// longest keyword to shortest, so comparing rune lengths preserves the full -// rebuild's start-position order. Equal lengths retain base-first order. -func (o *overlayEngine) emitMerged(base *outputs, baseState int, added *outputs, addedState, end int, - emit func(string, int, int) bool) bool { - for baseState != outNone || addedState != outNone { - baseState = nextOutput(base, baseState) - addedState = nextOutput(added, addedState) - baseID, addedID := int32(0), int32(0) - if baseState != outNone { - baseID = base.own[baseState] - } - if addedState != outNone { - addedID = added.own[addedState] - } - if baseID == 0 && addedID == 0 { - return true - } - if addedID == 0 || baseID != 0 && base.runeLens[baseID] >= added.runeLens[addedID] { - baseState = int(base.outLink[baseState]) - keyword := base.keywords[baseID] - if _, removed := o.removed[keyword]; !removed && !emit(keyword, end-int(base.runeLens[baseID]), end) { - return false - } - } else { - addedState = int(added.outLink[addedState]) - if !emit(added.keywords[addedID], end-int(added.runeLens[addedID]), end) { - return false - } - } - } - return true -} - -func nextOutput(out *outputs, state int) int { - for state != outNone && out.own[state] == 0 { - state = int(out.outLink[state]) - } - return state -} - -// appendMerged is the Find collector's direct path. Avoiding a callback here -// matters because Find reports every occurrence and can call it many times. -func (o *overlayEngine) appendMerged(dst []string, base *outputs, baseState int, - added *outputs, addedState int) []string { - for baseState != outNone || addedState != outNone { - baseState = nextOutput(base, baseState) - addedState = nextOutput(added, addedState) - if baseState == outNone && addedState == outNone { - break - } - if addedState == outNone || baseState != outNone && - base.runeLens[base.own[baseState]] >= added.runeLens[added.own[addedState]] { - keyword := base.keywords[base.own[baseState]] - baseState = int(base.outLink[baseState]) - if _, removed := o.removed[keyword]; !removed { - dst = append(dst, keyword) - } - } else { - dst = append(dst, added.keywords[added.own[addedState]]) - addedState = int(added.outLink[addedState]) - } - } - return dst -} - -func overlayMatchOrder(a, b overlayMatch) int { - if a.start != b.start { - return a.start - b.start - } - if a.source != b.source { - return a.source - b.source - } - return a.order - b.order -} - -func (o *overlayEngine) matchStream(next func() (rune, bool), emit func(string, int, int) bool) { - base, baseOK := o.base.impl.(*memEfficientEngine) - added, addedOK := o.added.impl.(*memEfficientEngine) - if !baseOK || !addedOK { - o.matchStreamWindow(next, emit) - return - } - if added.trie.out.keywordCount() == 0 { - o.base.Stream(next, func(k string, start, end int) bool { - if _, removed := o.removed[k]; removed { - return true - } - return emit(k, start, end) - }) - return - } - baseState, addedState, end := 0, 0, 0 - for { - ch, ok := next() - if !ok { - return - } - end++ - baseState = base.advance(baseState, ch) - addedState = added.advance(addedState, ch) - if base.trie.out.own[baseState] == 0 && base.trie.out.outLink[baseState] == outNone && - added.trie.out.own[addedState] == 0 && added.trie.out.outLink[addedState] == outNone { - continue - } - if !o.emitMerged(&base.trie.out, baseState, &added.trie.out, addedState, end, emit) { - return - } - } -} - -// Other presets can still be overlaid. Keep only enough input to decide the -// matches ending at the current rune, so a stopped callback never reads ahead. -func (o *overlayEngine) matchStreamWindow(next func() (rune, bool), emit func(string, int, int) bool) { - longest := max(o.base.MaxKeywordRunes(), o.added.MaxKeywordRunes()) - window := make([]rune, 0, longest) - end := 0 - for { - ch, ok := next() - if !ok { - return - } - end++ - window = append(window, ch) - if len(window) > longest { - copy(window, window[1:]) - window = window[:longest] - } - startOffset := end - len(window) - matches := make([]overlayMatch, 0, 8) - o.base.MatchString(string(window), func(k string, start, localEnd int) bool { - if localEnd == len(window) { - if _, removed := o.removed[k]; !removed { - matches = append(matches, overlayMatch{k, startOffset + start, end, 0, len(matches)}) - } - } - return true - }) - o.added.MatchString(string(window), func(k string, start, localEnd int) bool { - if localEnd == len(window) { - matches = append(matches, overlayMatch{k, startOffset + start, end, 1, len(matches)}) - } - return true - }) - if len(matches) > 1 { - slices.SortStableFunc(matches, overlayMatchOrder) - } - for _, m := range matches { - if !emit(m.keyword, m.start, m.end) { - return - } - } - } -} - -func (e *memEfficientEngine) advance(state int, ch rune) int { - if e.bloom.skipAtRoot(state == 0, ch) { - return 0 - } - for { - if next, ok := e.trie.nodes[state].next(ch); ok { - return next - } - if state == 0 { - return 0 - } - state = e.trie.nodes[state].fail - } -} - -func (o *overlayEngine) find(text string) []string { - if o.literal != nil && len(text) <= literalQueryLimit { - return o.findLiteral(text) - } - if !o.added.Contains(text) { - base := o.base.Find(text) - out := base[:0] - for _, k := range base { - if _, deleted := o.removed[k]; !deleted { - out = append(out, k) - } - } - return out - } - base, baseOK := o.base.impl.(*memEfficientEngine) - added, addedOK := o.added.impl.(*memEfficientEngine) - if !baseOK || !addedOK { - out := []string{} - o.matchString(text, func(k string, _, _ int) bool { out = append(out, k); return true }) - return out - } - out := []string{} - baseState, addedState := 0, 0 - for _, ch := range text { - baseState = base.advance(baseState, ch) - addedState = added.advance(addedState, ch) - if base.trie.out.own[baseState] == 0 && base.trie.out.outLink[baseState] == outNone && - added.trie.out.own[addedState] == 0 && added.trie.out.outLink[addedState] == outNone { - continue - } - out = o.appendMerged(out, &base.trie.out, baseState, &added.trie.out, addedState) - } - return out -} - -//nolint:gocyclo // Find avoids callback overhead in the same hot scan. -func (o *overlayEngine) findLiteral(text string) []string { - var hitBuffer [8]literalHit - hits := o.literal.matches(text, hitBuffer[:0]) - if len(hits) == 0 { - base := o.base.Find(text) - if len(o.removed) == 0 { - return base - } - out := base[:0] - for _, keyword := range base { - if _, removed := o.removed[keyword]; !removed { - out = append(out, keyword) - } - } - return out - } - base := o.base.impl.(*memEfficientEngine) - outputs := &base.trie.out - out := []string{} - state, hitIndex := 0, 0 - for pos, ch := range text { - if !base.bloom.skipAtRoot(state == 0, ch) { - for { - if next, ok := base.trie.nodes[state].next(ch); ok { - state = next - break - } - if state == 0 { - break - } - state = base.trie.nodes[state].fail - } - } - endByte := pos + 1 - baseState := nextOutput(outputs, state) - for baseState != outNone || hitIndex < len(hits) && hits[hitIndex].endByte == endByte { - baseID := int32(0) - if baseState != outNone { - baseID = outputs.own[baseState] - } - if hitIndex == len(hits) || hits[hitIndex].endByte != endByte || - baseID != 0 && int(outputs.runeLens[baseID]) >= hits[hitIndex].length { - keyword := outputs.keywords[baseID] - baseState = nextOutput(outputs, int(outputs.outLink[baseState])) - if _, removed := o.removed[keyword]; !removed { - out = append(out, keyword) - } - } else { - out = append(out, hits[hitIndex].keyword) - hitIndex++ - } - } - } - return out -} -func (o *overlayEngine) findSet(text string) []string { - if o.literal != nil && len(text) <= literalQueryLimit && strings.Contains(text, o.literal.prefix) { - out := []string{} - seen := make(map[string]struct{}) - o.matchStringLiteral(text, func(k string, _, _ int) bool { - if _, ok := seen[k]; !ok { - seen[k] = struct{}{} - out = append(out, k) - } - return true - }) - return out - } - if o.literal != nil && len(text) <= literalQueryLimit || !o.added.Contains(text) { - base := o.base.FindSet(text) - if len(o.removed) == 0 { - return base - } - out := base[:0] - for _, k := range base { - if _, deleted := o.removed[k]; !deleted { - out = append(out, k) - } - } - return out - } - out := []string{} - seen := make(map[string]struct{}) - o.matchString(text, func(k string, _, _ int) bool { - if _, ok := seen[k]; !ok { - seen[k] = struct{}{} - out = append(out, k) - } - return true - }) - return out -} -func (o *overlayEngine) findIndex(text string) map[string][]int { - if o.literal != nil && len(text) <= literalQueryLimit && strings.Contains(text, o.literal.prefix) { - out := make(map[string][]int) - o.matchStringLiteral(text, func(k string, start, _ int) bool { out[k] = append(out[k], start); return true }) - return out - } - if o.literal != nil && len(text) <= literalQueryLimit || !o.added.Contains(text) { - out := o.base.FindIndex(text) - if len(o.removed) == 0 { - return out - } - for k := range o.removed { - delete(out, k) - } - return out - } - out := make(map[string][]int) - o.matchString(text, func(k string, start, _ int) bool { out[k] = append(out[k], start); return true }) - return out -} -func (o *overlayEngine) contains(text string) bool { - if len(o.removed) == 0 { - if o.base.Contains(text) { - return true - } - } else { - found := false - o.base.MatchString(text, func(k string, _, _ int) bool { - if _, deleted := o.removed[k]; !deleted { - found = true - return false - } - return true - }) - if found { - return true - } - } - if o.literal != nil && !strings.Contains(text, o.literal.prefix) { - return false - } - return o.added.Contains(text) -} - -func (o *overlayEngine) info() *InMemoryInfo { - i := *o.base.Info() - i.Keywords += o.added.Info().Keywords - len(o.removed) - i.MemoryBytes += o.added.Info().MemoryBytes + int64(len(o.removed))*32 - i.TrieDepth = max(i.TrieDepth, o.added.Info().TrieDepth) - return &i -} diff --git a/internal/engine/overlay_bench_test.go b/internal/engine/overlay_bench_test.go deleted file mode 100644 index 1a333a2..0000000 --- a/internal/engine/overlay_bench_test.go +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package engine - -import ( - "fmt" - "slices" - "strings" - "testing" -) - -// BenchmarkOverlayCosts separates the added.Contains pre-scan, the second -// automaton traversal, and the former per-rune collect/sort path. It is a -// diagnostic benchmark, not a release gate: the real-server matrix measures -// the public V3 calls and process RSS. -func BenchmarkOverlayCosts(b *testing.B) { - words := make(map[string]struct{}, 10000) - for i := range 10000 { - words[fmt.Sprintf("common-prefix-keyword-%05d", i)] = struct{}{} - } - base := New(PresetMemoryEfficient) - base.Build(words) - added := New(PresetMemoryEfficient) - added.Build(map[string]struct{}{"delta-keyword": {}, "delta": {}, "delta-keyword-long": {}}) - overlay := Overlay(base, added, nil) - for name, query := range map[string]string{ - "added_hit": strings.Repeat("common-prefix-keyword-00123 delta-keyword ", 8), - "single_hit": "common-prefix-keyword-00123 common-prefix-keyword-04123 delta-keyword common-prefix-keyword-09999", - "delta_miss": strings.Repeat("common-prefix-keyword-00123 no-change-here ", 8), - } { - b.Run(name, func(b *testing.B) { - b.Run("base", func(b *testing.B) { - b.ReportAllocs() - for range b.N { - _ = base.Find(query) - } - }) - b.Run("added_precheck", func(b *testing.B) { - b.ReportAllocs() - for range b.N { - _ = added.Contains(query) - } - }) - b.Run("two_traversals", func(b *testing.B) { - b.ReportAllocs() - for range b.N { - _ = base.Find(query) - _ = added.Find(query) - } - }) - b.Run("collect_sort", func(b *testing.B) { - b.ReportAllocs() - for range b.N { - _ = oldOverlayFind(base.impl.(*memEfficientEngine), added.impl.(*memEfficientEngine), query) - } - }) - b.Run("merged", func(b *testing.B) { - b.ReportAllocs() - for range b.N { - _ = overlay.Find(query) - } - }) - b.Run("merged_scan", func(b *testing.B) { - b.ReportAllocs() - for range b.N { - var out []string - overlay.MatchString(query, func(k string, _, _ int) bool { - out = append(out, k) - return true - }) - } - }) - }) - } -} - -// oldOverlayFind models the original additional-hit branch so its allocation -// and CPU cost can be compared on the same dictionary and query. -func oldOverlayFind(base, added *memEfficientEngine, text string) []string { - baseState, addedState, end := 0, 0, 0 - matches := make([]overlayMatch, 0, 8) - out := []string{} - for _, ch := range text { - end++ - matches = matches[:0] - baseState = base.advance(baseState, ch) - base.trie.out.emitChain(baseState, end, func(k string, start, end int) bool { - matches = append(matches, overlayMatch{k, start, end, 0, len(matches)}) - return true - }) - addedState = added.advance(addedState, ch) - added.trie.out.emitChain(addedState, end, func(k string, start, end int) bool { - matches = append(matches, overlayMatch{k, start, end, 1, len(matches)}) - return true - }) - if len(matches) > 1 { - slices.SortStableFunc(matches, overlayMatchOrder) - } - for _, m := range matches { - out = append(out, m.keyword) - } - } - return out -} diff --git a/internal/engine/overlay_test.go b/internal/engine/overlay_test.go deleted file mode 100644 index 8709782..0000000 --- a/internal/engine/overlay_test.go +++ /dev/null @@ -1,197 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package engine - -import ( - "reflect" - "strings" - "testing" -) - -func TestOverlayMatchesRebuild(t *testing.T) { - base := New(PresetMemoryEfficient) - base.Build(map[string]struct{}{"he": {}, "she": {}, "hers": {}, "한국": {}, "old": {}}) - added := New(PresetMemoryEfficient) - added.Build(map[string]struct{}{"her": {}, "한국어": {}}) - overlay := Overlay(base, added, map[string]struct{}{"old": {}}) - full := New(PresetMemoryEfficient) - full.Build(map[string]struct{}{"he": {}, "she": {}, "hers": {}, "한국": {}, "her": {}, "한국어": {}}) - text := strings.Repeat("ushers old 한국어 ", 300) - if got, want := overlay.Find(text), full.Find(text); !reflect.DeepEqual(got, want) { - t.Fatal("find differs") - } - if got, want := overlay.FindIndex(text), full.FindIndex(text); !reflect.DeepEqual(got, want) { - t.Fatal("index differs") - } - if got, want := overlay.FindSet(text), full.FindSet(text); !reflect.DeepEqual(got, want) { - t.Fatal("set differs") - } - collect := func(e *Engine) []string { - var out []string - runes := []rune(text) - i := 0 - e.Stream(func() (rune, bool) { - if i == len(runes) { - return 0, false - } - r := runes[i] - i++ - return r, true - }, - func(k string, start, end int) bool { out = append(out, k); return true }) - return out - } - if got, want := collect(overlay), collect(full); !reflect.DeepEqual(got, want) { - t.Fatal("stream differs") - } -} - -func TestOverlayStopsAtFirstMatch(t *testing.T) { - base := New(PresetMemoryEfficient) - base.Build(map[string]struct{}{"a": {}, "aa": {}}) - added := New(PresetMemoryEfficient) - added.Build(map[string]struct{}{"aaa": {}}) - overlay := Overlay(base, added, nil) - text := strings.Repeat("a", 100000) - called := 0 - overlay.MatchString(text, func(k string, start, end int) bool { - called++ - return false - }) - if called != 1 { - t.Fatalf("callback called %d times", called) - } - read := 0 - overlay.Stream(func() (rune, bool) { - read++ - if read > 1 { - t.Fatal("stream read beyond first match") - } - return 'a', true - }, func(string, int, int) bool { return false }) - if read != 1 { - t.Fatalf("stream read %d runes", read) - } -} - -func TestOverlayMergedOutputOrderAndSpans(t *testing.T) { - base := New(PresetMemoryEfficient) - base.Build(map[string]struct{}{"a": {}, "aa": {}, "aaa": {}, "ba": {}, "old": {}, "한국": {}}) - added := New(PresetMemoryEfficient) - added.Build(map[string]struct{}{"aaaa": {}, "baa": {}, "한국어": {}}) - overlay := Overlay(base, added, map[string]struct{}{"old": {}, "aa": {}}) - full := New(PresetMemoryEfficient) - full.Build(map[string]struct{}{"a": {}, "aaa": {}, "ba": {}, "한국": {}, "aaaa": {}, "baa": {}, "한국어": {}}) - for _, text := range []string{"baaaa old 한국어 baaaa", "aaaaa", "nothing", "한국어 aaaa"} { - collect := func(e *Engine, stream bool) [][3]any { - var matches [][3]any - emit := func(k string, start, end int) bool { - matches = append(matches, [3]any{k, start, end}) - return true - } - if stream { - runes := []rune(text) - i := 0 - e.Stream(func() (rune, bool) { - if i == len(runes) { - return 0, false - } - r := runes[i] - i++ - return r, true - }, emit) - } else { - e.MatchString(text, emit) - } - return matches - } - for _, stream := range []bool{false, true} { - if got, want := collect(overlay, stream), collect(full, stream); !reflect.DeepEqual(got, want) { - t.Fatalf("text=%q stream=%t: got %v, want %v", text, stream, got, want) - } - } - if got, want := overlay.Find(text), full.Find(text); !reflect.DeepEqual(got, want) { - t.Fatalf("Find(%q): got %v, want %v", text, got, want) - } - if got, want := overlay.FindSet(text), full.FindSet(text); !reflect.DeepEqual(got, want) { - t.Fatalf("FindSet(%q): got %v, want %v", text, got, want) - } - if got, want := overlay.FindIndex(text), full.FindIndex(text); !reflect.DeepEqual(got, want) { - t.Fatalf("FindIndex(%q): got %v, want %v", text, got, want) - } - if got, want := overlay.Contains(text), full.Contains(text); got != want { - t.Fatalf("Contains(%q): got %t, want %t", text, got, want) - } - } -} - -func TestOverlayLiteralCandidatesMatchRebuild(t *testing.T) { - base := New(PresetMemoryEfficient) - base.Build(map[string]struct{}{ - "delta": {}, "change": {}, "-001": {}, "old": {}, "한국": {}, - }) - added := New(PresetMemoryEfficient) - added.Build(map[string]struct{}{ - "delta-change": {}, "delta-change-001": {}, "delta-change-002": {}, - }) - overlay := Overlay(base, added, map[string]struct{}{"old": {}}) - if overlay.impl.(*overlayEngine).literal == nil { - t.Fatal("expected literal candidate path") - } - full := New(PresetMemoryEfficient) - full.Build(map[string]struct{}{ - "delta": {}, "change": {}, "-001": {}, "한국": {}, - "delta-change": {}, "delta-change-001": {}, "delta-change-002": {}, - }) - for _, text := range []string{ - "한국 delta-change-001 old delta-change-002 delta-change", - "delta-change-001delta-change-002", "delta-change-003", "absent", - "\xffdelta-change-001\xff", // Invalid input must retain rune offsets. - strings.Repeat("delta-change-001 ", 20), - strings.Repeat("delta-change-001 ", 300), // Long inputs use the automata. - } { - collect := func(e *Engine) [][3]any { - var matches [][3]any - e.MatchString(text, func(k string, start, end int) bool { - matches = append(matches, [3]any{k, start, end}) - return true - }) - return matches - } - if got, want := collect(overlay), collect(full); !reflect.DeepEqual(got, want) { - t.Fatalf("MatchString(%q): got %v, want %v", text, got, want) - } - if got, want := overlay.Find(text), full.Find(text); !reflect.DeepEqual(got, want) { - t.Fatalf("Find(%q): got %v, want %v", text, got, want) - } - if got, want := overlay.FindSet(text), full.FindSet(text); !reflect.DeepEqual(got, want) { - t.Fatalf("FindSet(%q): got %v, want %v", text, got, want) - } - if got, want := overlay.FindIndex(text), full.FindIndex(text); !reflect.DeepEqual(got, want) { - t.Fatalf("FindIndex(%q): got %v, want %v", text, got, want) - } - if got, want := overlay.Contains(text), full.Contains(text); got != want { - t.Fatalf("Contains(%q): got %t, want %t", text, got, want) - } - } - for _, e := range []*Engine{overlay, full} { - called := 0 - e.MatchString("delta-change-001 delta-change-002", func(string, int, int) bool { - called++ - return false - }) - if called != 1 { - t.Fatalf("early stop emitted %d matches", called) - } - } -} - -func TestOverlayEmptyDeltaSharesBase(t *testing.T) { - base := New(PresetMemoryEfficient) - base.Build(map[string]struct{}{"base": {}}) - added := New(PresetMemoryEfficient) - added.Build(nil) - if got := Overlay(base, added, nil); got != base { - t.Fatal("empty delta should reuse the base search view") - } -} diff --git a/pkg/acor/versioned.go b/pkg/acor/versioned.go index c7eb0d9..61604ce 100644 --- a/pkg/acor/versioned.go +++ b/pkg/acor/versioned.go @@ -34,9 +34,6 @@ const ( v3MillisPerSecond = 1000 v3PageHint = 1024 v3DebounceDefault = 20 * time.Millisecond - v3OverlayLimit = 128 - v3CompactDelay = time.Second - v3CompactPoll = 100 * time.Millisecond ) var ( @@ -62,8 +59,7 @@ type VersionedOptions struct { Redis AhoCorasickArgs CaseSensitive bool Preset Preset - // DeltaSearch enables the small-update search path for MemoryEfficient. - // It remains opt-in until the release-scale latency and RSS gates are met. + // DeltaSearch is retained for source compatibility; V3 always serves a single engine. DeltaSearch bool // PollInterval defaults to 30 seconds; negative values are invalid. PollInterval time.Duration @@ -114,17 +110,11 @@ type v3Bucket struct { Checksum string } type v3Engine struct { - engine *matchengine.Engine - base *matchengine.Engine - baseBuckets *[v3BucketCount][]string - baseManifest *v3Manifest - added map[string]struct{} - removed map[string]struct{} - version Version - sequence uint64 - manifest *v3Manifest - buckets *[v3BucketCount][]string - installed time.Time + engine *matchengine.Engine + version Version + sequence uint64 + manifest *v3Manifest + buckets *[v3BucketCount][]string } // VersionedCollection owns a V3 dictionary and a background engine refresher. @@ -197,8 +187,6 @@ func OpenVersioned(ctx context.Context, opts *VersionedOptions) (*VersionedColle } v.wg.Add(1) go v.refreshLoop() - v.wg.Add(1) - go v.compactLoop() return v, nil } @@ -286,9 +274,6 @@ func (v *VersionedCollection) refresh(ctx context.Context) error { if err != nil { return err } - if used, err := v.tryOverlay(ctx, s, buckets, downloaded, reused); used || err != nil { - return err - } e := matchengine.New(enginePreset(v.opts.Preset)) if buildErr := e.BuildSequenceContext(ctx, bucketSequence(buckets), s.Count()); buildErr != nil { return buildErr @@ -303,7 +288,7 @@ func (v *VersionedCollection) refresh(ctx context.Context) error { return nil } func (v *VersionedCollection) installEngine(s *Snapshot, e *matchengine.Engine, buckets *[v3BucketCount][]string, downloaded, reused int) { - v.current.Store(&v3Engine{engine: e, version: s.Version(), sequence: s.manifest.Sequence, manifest: s.manifest, buckets: buckets, installed: time.Now()}) + v.current.Store(&v3Engine{engine: e, version: s.Version(), sequence: s.manifest.Sequence, manifest: s.manifest, buckets: buckets}) v.mu.Lock() v.status.ServingVersion = s.Version() v.status.LastError = "" diff --git a/pkg/acor/versioned_delta_scale_test.go b/pkg/acor/versioned_delta_scale_test.go deleted file mode 100644 index dc2616d..0000000 --- a/pkg/acor/versioned_delta_scale_test.go +++ /dev/null @@ -1,284 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package acor - -import ( - "context" - "encoding/json" - "fmt" - "os" - "runtime" - "slices" - "strconv" - "strings" - "syscall" - "testing" - "time" -) - -// TestVersionedDeltaScale compares the opt-in path against the full rebuild in -// fresh processes. The companion script owns the server and repeats each run. -// -//nolint:gocyclo,funlen // Opt-in real-server measurement keeps operation ordering explicit. -func TestVersionedDeltaScale(t *testing.T) { - addr := os.Getenv("ACOR_V3_SCALE_ADDR") - if addr == "" { - t.Skip("set ACOR_V3_SCALE_ADDR to a disposable real server") - } - n, err := strconv.Atoi(os.Getenv("ACOR_V3_SCALE_N")) - if err != nil || n < 129 { - t.Fatal("ACOR_V3_SCALE_N must be at least 129") - } - kind := os.Getenv("ACOR_V3_SCALE_KIND") - words := v3ScaleWords(n, kind) - delta := os.Getenv("ACOR_V3_SCALE_DELTA") == "1" - ctx := context.Background() - opts := &VersionedOptions{Redis: AhoCorasickArgs{Addr: addr, Name: "delta-scale-" + v3ID()}, - PollInterval: 50 * time.Millisecond, DeltaSearch: delta} - v, err := OpenVersioned(ctx, opts) - if err != nil { - t.Fatal(err) - } - defer v3DeleteTestKeys(ctx, t, v) - defer func() { _ = v.Close() }() - serverInfo, _ := v.client.Info(ctx, "server").Result() - t.Logf("environment go=%s os=%s arch=%s cpus=%d n=%d kind=%s delta=%t seed=20260906 server=%s", - runtime.Version(), runtime.GOOS, runtime.GOARCH, runtime.NumCPU(), n, kind, delta, - strings.ReplaceAll(serverInfo, "\r\n", " ")) - r, err := v.Replace(ctx, v.Status().ServingVersion, words) - if err != nil { - t.Fatal(err) - } - if err = v.WaitForVersion(ctx, r.Version); err != nil { - t.Fatal(err) - } - if v.Status().DeltaSearch { - t.Fatal("initial load unexpectedly used delta search") - } - version := r.Version - change := make([]string, 129) - for i := range change { - change[i] = fmt.Sprintf("delta-change-%03d", i) - } - measure := func(label string, expectedDelta bool, write func(Version) (*WriteResult, error)) { - t.Helper() - start := time.Now() - r, e := write(version) - commit := time.Since(start) - if e != nil { - t.Fatal(label, e) - } - if e = v.WaitForVersion(ctx, r.Version); e != nil { - t.Fatal(label, e) - } - ready := time.Since(start) - version = r.Version - status := v.Status() - if status.DeltaSearch != (delta && expectedDelta) { - t.Fatalf("%s: unexpected search mode: %+v", label, status) - } - // Include an unchanged base word and a changed word. The same input is - // used for both modes, including after removal. - query := words[0] + " " + words[n/2] + " " + change[0] + " " + words[n-1] - found, e := v.FindSet(ctx, query) - if e != nil || !slices.Contains(found, words[0]) || slices.Contains(found, words[n/2]) == (label == "remove_base_1") || - !slices.Contains(found, words[n-1]) || slices.Contains(found, change[0]) != strings.HasPrefix(label, "add_") { - t.Fatalf("%s: serving search mismatch: %v (%v)", label, found, e) - } - latencies := make([]int64, 0, 512) - until := time.Now().Add(500 * time.Millisecond) - for time.Now().Before(until) { - searchStart := time.Now() - if _, e := v.Find(ctx, query); e != nil { - t.Fatal(label, e) - } - latencies = append(latencies, time.Since(searchStart).Nanoseconds()) - time.Sleep(time.Millisecond) - } - slices.Sort(latencies) - apiStart := time.Now() - buildingBeforeAPI := v.Status().Building - apiSamples := v3DeltaAPISamples(t, v, ctx, query, label) - buildingAfterAPI := v.Status().Building - if current := v.Status(); current.ServingVersion != version || - current.DeltaSearch != (delta && expectedDelta) { - t.Fatalf("%s: serving mode changed during API sample: %+v", label, current) - } - var heap runtime.MemStats - runtime.ReadMemStats(&heap) - record := map[string]any{ - "operation": label, "n": n, "kind": kind, "delta_enabled": delta, - "delta_serving": status.DeltaSearch, "delta_keywords": status.DeltaKeywords, - "commit_ms": float64(commit.Microseconds()) / 1000, - "ready_ms": float64(ready.Microseconds()) / 1000, - "search_p95_ns": latencies[(len(latencies)-1)*95/100], - "search_samples": len(latencies), - "rss_highwater_at_sample_bytes": v3ProcessMaxRSS(), - "heap_alloc_at_sample_bytes": heap.Alloc, - "downloaded_buckets": status.DownloadedBuckets, - "reused_buckets": status.ReusedBuckets, - "search_apis": apiSamples, - "api_sample_ms": float64(time.Since(apiStart).Microseconds()) / 1000, - "building_during_api": buildingBeforeAPI || buildingAfterAPI, - } - data, _ := json.Marshal(record) - t.Log(string(data)) - } - measure("add_1", true, func(vn Version) (*WriteResult, error) { return v.Add(ctx, vn, change[0]) }) - measure("remove_1", true, func(vn Version) (*WriteResult, error) { return v.Remove(ctx, vn, change[0]) }) - measure("add_128", true, func(vn Version) (*WriteResult, error) { return v.AddMany(ctx, vn, change[:128]) }) - measure("remove_128", true, func(vn Version) (*WriteResult, error) { return v.RemoveMany(ctx, vn, change[:128]) }) - measure("remove_base_1", true, func(vn Version) (*WriteResult, error) { return v.Remove(ctx, vn, words[n/2]) }) - restored, err := v.Add(ctx, version, words[n/2]) - if err != nil { - t.Fatal("restore base word", err) - } - if err = v.WaitForVersion(ctx, restored.Version); err != nil { - t.Fatal("restore base word", err) - } - version = restored.Version - measure("add_129", false, func(vn Version) (*WriteResult, error) { return v.AddMany(ctx, vn, change) }) - measure("remove_129", false, func(vn Version) (*WriteResult, error) { return v.RemoveMany(ctx, vn, change) }) - // A final small update is left idle to observe the full compaction's cost. - measure("add_1_compact", true, func(vn Version) (*WriteResult, error) { return v.Add(ctx, vn, change[0]) }) - compactStart := time.Now() - compactLatencies := make([]int64, 0, 512) - if delta { - deadline := time.Now().Add(2 * time.Minute) - for v.Status().DeltaSearch && time.Now().Before(deadline) { - searchStart := time.Now() - if _, err := v.Find(ctx, words[0]+" "+change[0]); err != nil { - t.Fatal("search during compaction", err) - } - compactLatencies = append(compactLatencies, time.Since(searchStart).Nanoseconds()) - time.Sleep(time.Millisecond) - } - if v.Status().DeltaSearch { - t.Fatal("compaction did not complete") - } - } - if got, err := v.FindSet(ctx, change[0]); err != nil || !slices.Equal(got, []string{change[0]}) { - t.Fatal("post-compaction search", got, err) - } - slices.Sort(compactLatencies) - var compactP95 int64 - if len(compactLatencies) > 0 { - compactP95 = compactLatencies[(len(compactLatencies)-1)*95/100] - } - var heap runtime.MemStats - runtime.ReadMemStats(&heap) - data, _ := json.Marshal(map[string]any{"operation": "post_compaction", "n": n, "kind": kind, - "delta_enabled": delta, "compaction_wait_ms": float64(time.Since(compactStart).Microseconds()) / 1000, - "rss_highwater_at_sample_bytes": v3ProcessMaxRSS(), "heap_alloc_at_sample_bytes": heap.Alloc, - "compaction_search_p95_ns": compactP95, "compaction_search_samples": len(compactLatencies), - "delta_serving": v.Status().DeltaSearch}) - t.Log(string(data)) -} - -func v3ProcessMaxRSS() int64 { - var usage syscall.Rusage - if err := syscall.Getrusage(syscall.RUSAGE_SELF, &usage); err != nil { - return 0 - } - rss := usage.Maxrss - if runtime.GOOS != "darwin" { - rss *= 1024 - } - return rss -} - -// v3DeltaAPISamples uses identical text and call shapes in the paired modes. -// The parallel text exceeds ChunkSize many times; short texts exercise the -// ordinary local search path without making result construction dominate it. -// -//nolint:funlen // Each closure is a distinct public API under measurement. -func v3DeltaAPISamples(t *testing.T, v *VersionedCollection, ctx context.Context, query, label string) map[string]map[string]int64 { - t.Helper() - inputs := map[string]string{ - "change": query, - "delta_miss": "absent-delta-token-999999", - } - if label == "remove_base_1" { - inputs["removed_base"] = query - } else if strings.HasPrefix(label, "remove_") { - inputs["removed_change"] = query - } else { - inputs["added_hit"] = query - } - result := make(map[string]map[string]int64) - for _, inputKind := range []string{"change", "added_hit", "removed_change", "removed_base", "delta_miss"} { - text, exists := inputs[inputKind] - if !exists { - continue - } - parallelText := strings.Repeat(text+" ", 48) - parallelOpts := &ParallelOptions{Workers: 2, ChunkSize: 128, AutoOverlap: true} - batch := []string{text, text, "absent-delta-token-999999"} - calls := map[string]func() error{ - "Find": func() error { _, err := v.Find(ctx, text); return err }, - "FindSet": func() error { _, err := v.FindSet(ctx, text); return err }, - "FindIndex": func() error { _, err := v.FindIndex(ctx, text); return err }, - "FindMatches": func() error { _, err := v.FindMatches(ctx, text, nil); return err }, - "Contains": func() error { _, err := v.Contains(ctx, text); return err }, - "FindStream": func() error { - return v.FindStream(ctx, strings.NewReader(text), func(Match) bool { return true }) - }, - "FindBatch": func() error { _, err := v.FindBatch(ctx, batch); return err }, - "FindParallel": func() error { _, err := v.FindParallel(ctx, parallelText, parallelOpts); return err }, - "FindIndexParallel": func() error { _, err := v.FindIndexParallel(ctx, parallelText, parallelOpts); return err }, - "Scan": func() error { _, err := v.Scan(ctx, text, nil); return err }, - "MaskText": func() error { _, err := v.MaskText(ctx, text, '*', nil); return err }, - "ReplaceText": func() error { _, err := v.ReplaceText(ctx, text, "[x]", nil); return err }, - } - for _, api := range []string{"Find", "FindSet", "FindIndex", "FindMatches", "Contains", "FindStream", - "FindBatch", "FindParallel", "FindIndexParallel", "Scan", "MaskText", "ReplaceText"} { - call := calls[api] - latencies := make([]int64, 128) - for i := range latencies { - start := time.Now() - if err := call(); err != nil { - t.Fatalf("%s/%s/%s: %v", label, inputKind, api, err) - } - latencies[i] = time.Since(start).Nanoseconds() - } - slices.Sort(latencies) - if result[api] == nil { - result[api] = make(map[string]int64) - } - result[api][inputKind] = latencies[(len(latencies)-1)*95/100] - } - } - return result -} - -func v3DeleteTestKeys(ctx context.Context, t *testing.T, v *VersionedCollection) { - t.Helper() - c, err := newRedisClient(&v.opts.Redis) - if err != nil { - t.Log("cleanup connection:", err) - return - } - defer c.Close() - var cursor uint64 - var allKeys []string - for { - keys, next, err := c.Scan(ctx, cursor, v.prefix+"*", 256).Result() - if err != nil { - t.Log("cleanup scan:", err) - return - } - allKeys = append(allKeys, keys...) - cursor = next - if cursor == 0 { - break - } - } - for len(allKeys) > 0 { - batch := allKeys[:min(len(allKeys), 256)] - if err := c.Del(ctx, batch...).Err(); err != nil { - t.Log("cleanup delete:", err) - return - } - allKeys = allKeys[len(batch):] - } -} diff --git a/pkg/acor/versioned_overlay.go b/pkg/acor/versioned_overlay.go deleted file mode 100644 index 158ba6d..0000000 --- a/pkg/acor/versioned_overlay.go +++ /dev/null @@ -1,185 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package acor - -import ( - "context" - "iter" - "time" - - matchengine "github.com/skyoo2003/acor/internal/engine" -) - -func v3MapSequence(words map[string]struct{}) iter.Seq[string] { - return func(yield func(string) bool) { - for word := range words { - if !yield(word) { - return - } - } - } -} - -// Compare the target to the dictionary represented by the base automaton. -// Unchanged buckets share their backing slice and cost no per-word work. -func v3BucketDelta(previous *v3Engine, target *v3Manifest, next *[v3BucketCount][]string) (added, removed map[string]struct{}) { - base := previous.baseBuckets - if base == nil { - base = previous.buckets - } - manifest := previous.baseManifest - if manifest == nil { - manifest = previous.manifest - } - added = make(map[string]struct{}) - removed = make(map[string]struct{}) - for i := range next { - if sameBucket(manifest.Buckets[i], target.Buckets[i]) { - continue - } - old := make(map[string]struct{}, len(base[i])) - for _, word := range base[i] { - old[word] = struct{}{} - } - for _, word := range next[i] { - if _, ok := old[word]; ok { - delete(old, word) - } else { - added[word] = struct{}{} - } - } - for word := range old { - removed[word] = struct{}{} - } - } - return added, removed -} - -func (v *VersionedCollection) tryOverlay(ctx context.Context, s *Snapshot, buckets *[v3BucketCount][]string, - downloaded, reused int) (bool, error) { - previous := v.current.Load() - if previous == nil || !v.opts.DeltaSearch || v.opts.Preset != PresetMemoryEfficient { - return false, nil - } - base := previous.base - if base == nil { - base = previous.engine - } - added, removed := v3BucketDelta(previous, s.manifest, buckets) - if len(added)+len(removed) > v3OverlayLimit { - return false, nil - } - addition := matchengine.New(enginePreset(v.opts.Preset)) - if err := addition.BuildSequenceContext(ctx, v3MapSequence(added), len(added)); err != nil { - return true, err - } - if err := s.lease.check(ctx); err != nil { - return true, err - } - if err := v.check(ctx); err != nil { - return true, err - } - v.installOverlay(s, base, addition, added, removed, buckets, downloaded, reused) - return true, nil -} - -func (v *VersionedCollection) installOverlay(s *Snapshot, base, addition *matchengine.Engine, - added, removed map[string]struct{}, buckets *[v3BucketCount][]string, downloaded, reused int) { - previous := v.current.Load() - baseBuckets := previous.baseBuckets - if baseBuckets == nil { - baseBuckets = previous.buckets - } - baseManifest := previous.baseManifest - if baseManifest == nil { - baseManifest = previous.manifest - } - v.current.Store(&v3Engine{engine: matchengine.Overlay(base, addition, removed), base: base, baseBuckets: baseBuckets, - baseManifest: baseManifest, - added: added, removed: removed, version: s.Version(), sequence: s.manifest.Sequence, - manifest: s.manifest, buckets: buckets, installed: time.Now()}) - v.mu.Lock() - v.status.ServingVersion = s.Version() - v.status.LastError = "" - v.status.DownloadedBuckets = downloaded - v.status.ReusedBuckets = reused - v.status.CompletedBuilds++ - v.status.DeltaSearch = true - v.status.DeltaKeywords = len(added) + len(removed) - v.mu.Unlock() -} - -func (v *VersionedCollection) compactLoop() { - defer v.wg.Done() - ticker := time.NewTicker(v3CompactPoll) - defer ticker.Stop() - for { - select { - case <-v.ctx.Done(): - return - case <-ticker.C: - v.compactIfIdle(v.ctx) - } - } -} - -func (v *VersionedCollection) compactIfIdle(ctx context.Context) { - current := v.current.Load() - if current == nil || current.base == nil || time.Since(current.installed) < v3CompactDelay { - return - } - if v.current.Load() != current || ctx.Err() != nil { - return - } - start := time.Now() - v.mu.Lock() - v.status.Building = true - v.status.BuildStarted = start - v.mu.Unlock() - defer func() { - v.mu.Lock() - if v.current.Load() == current { - v.status.Building = false - v.status.BuildDuration = time.Since(start) - } - v.mu.Unlock() - }() - e := matchengine.New(enginePreset(v.opts.Preset)) - if err := e.BuildSequenceContext(ctx, bucketSequence(current.buckets), current.manifest.Count); err != nil { - if v.current.Load() == current { - v.recordCompactError(err) - } - return - } - active, err := v.client.Get(ctx, v.key("active")).Result() - if err != nil { - if v.current.Load() == current { - v.recordCompactError(err) - } - return - } - v.refreshMu.Lock() - defer v.refreshMu.Unlock() - if Version(active) != current.version || v.current.Load() != current || ctx.Err() != nil { - return - } - v.current.Store(&v3Engine{engine: e, version: current.version, sequence: current.sequence, - manifest: current.manifest, buckets: current.buckets, installed: time.Now()}) - v.mu.Lock() - v.status.Building = false - v.status.BuildDuration = time.Since(start) - v.status.LastError = "" - v.status.CompletedBuilds++ - v.status.DeltaSearch = false - v.status.DeltaKeywords = 0 - v.mu.Unlock() -} - -func (v *VersionedCollection) recordCompactError(err error) { - if v.ctx.Err() != nil { - return - } - v.mu.Lock() - v.status.LastError = err.Error() - v.mu.Unlock() -} diff --git a/pkg/acor/versioned_overlay_parity_test.go b/pkg/acor/versioned_overlay_parity_test.go index 750c14a..da189d1 100644 --- a/pkg/acor/versioned_overlay_parity_test.go +++ b/pkg/acor/versioned_overlay_parity_test.go @@ -14,7 +14,7 @@ import ( "github.com/alicebob/miniredis/v2" ) -//nolint:gocyclo,funlen // One scenario compares every public search entry point at the same overlay version. +//nolint:gocyclo,funlen // One scenario compares every public search entry point at the same V3 version. func TestVersionedOverlaySearchAPIParity(t *testing.T) { ctx := context.Background() server := miniredis.RunT(t) @@ -28,7 +28,7 @@ func TestVersionedOverlaySearchAPIParity(t *testing.T) { t.Cleanup(func() { _ = v.Close() }) return v } - delta := open("overlay-api-parity", true) + delta := open("single-engine-api-parity", true) full := open("full-api-parity", false) base := []string{"he", "old", "한국", "aa"} for i := 0; i < 129; i++ { @@ -51,8 +51,8 @@ func TestVersionedOverlaySearchAPIParity(t *testing.T) { } waitV3(t, v, r.Version) } - if status := delta.Status(); !status.DeltaSearch || status.DeltaKeywords != 5 { - t.Fatalf("expected composed overlay, got %+v", status) + if status := delta.Status(); status.DeltaSearch || status.DeltaKeywords != 0 { + t.Fatalf("expected single engine, got %+v", status) } text := strings.Repeat("ushers old 한국어 aaaa word-001 ", 5) compare := func(name string, a, b any, errA, errB error) { @@ -109,20 +109,11 @@ func TestVersionedOverlaySearchAPIParity(t *testing.T) { breplace, be := full.ReplaceText(ctx, input, "[x]", nil) compare("ReplaceText", areplace, breplace, ae, be) } - if delta.Status().DeltaSearch { - deadline := time.Now().Add(5 * time.Second) - for delta.Status().DeltaSearch && time.Now().Before(deadline) { - time.Sleep(10 * time.Millisecond) - } - } - if delta.Status().DeltaSearch { - t.Fatal("compaction did not complete") - } a, ea = delta.Find(ctx, text) - compare("post-compaction Find", a, b, ea, eb) + compare("post-refresh Find", a, b, ea, eb) } -func TestVersionedOverlayFallsBackAboveLimit(t *testing.T) { +func TestVersionedDeltaOptionUsesSingleEngine(t *testing.T) { ctx := context.Background() server := miniredis.RunT(t) v, err := OpenVersioned(ctx, &VersionedOptions{Redis: AhoCorasickArgs{Addr: server.Addr(), Name: "overlay-limit"}, @@ -147,8 +138,8 @@ func TestVersionedOverlayFallsBackAboveLimit(t *testing.T) { t.Fatal(err) } waitV3(t, v, r.Version) - if s := v.Status(); !s.DeltaSearch || s.DeltaKeywords != 128 { - t.Fatalf("limit case: %+v", s) + if s := v.Status(); s.DeltaSearch || s.DeltaKeywords != 0 { + t.Fatalf("single-engine case: %+v", s) } r, err = v.Add(ctx, r.Version, change[128]) if err != nil { @@ -156,11 +147,11 @@ func TestVersionedOverlayFallsBackAboveLimit(t *testing.T) { } waitV3(t, v, r.Version) if s := v.Status(); s.DeltaSearch || s.DeltaKeywords != 0 { - t.Fatalf("above-limit fallback: %+v", s) + t.Fatalf("second update: %+v", s) } } -func TestVersionedOverlayRapidUpdates(t *testing.T) { +func TestVersionedRapidUpdatesUseSingleEngine(t *testing.T) { ctx := context.Background() server := miniredis.RunT(t) v, err := OpenVersioned(ctx, &VersionedOptions{Redis: AhoCorasickArgs{Addr: server.Addr(), Name: "overlay-rapid"}, @@ -185,18 +176,11 @@ func TestVersionedOverlayRapidUpdates(t *testing.T) { } waitV3(t, v, r.Version) } - if s := v.Status(); !s.DeltaSearch || s.DeltaKeywords != 20 || s.ServingVersion != r.Version { - t.Fatalf("latest update not served by overlay: %+v", s) + if s := v.Status(); s.DeltaSearch || s.DeltaKeywords != 0 || s.ServingVersion != r.Version { + t.Fatalf("latest update not served by single engine: %+v", s) } if got, err := v.FindSet(ctx, "new-000 new-019 base-001"); err != nil || !reflect.DeepEqual(got, []string{"new-000", "new-019", "base-001"}) { t.Fatal("latest search", got, err) } - deadline := time.Now().Add(5 * time.Second) - for v.Status().DeltaSearch && time.Now().Before(deadline) { - time.Sleep(10 * time.Millisecond) - } - if s := v.Status(); s.DeltaSearch || s.ServingVersion != r.Version { - t.Fatalf("compaction lost latest version: %+v", s) - } } diff --git a/pkg/acor/versioned_overlay_test.go b/pkg/acor/versioned_overlay_test.go deleted file mode 100644 index a169216..0000000 --- a/pkg/acor/versioned_overlay_test.go +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package acor - -import ( - "context" - "fmt" - "reflect" - "strings" - "testing" - "time" - - "github.com/alicebob/miniredis/v2" -) - -//nolint:gocyclo // Lifecycle assertions cover publication, search, and compaction together. -func TestVersionedOverlayLifecycle(t *testing.T) { - ctx := context.Background() - server := miniredis.RunT(t) - v, err := OpenVersioned(ctx, &VersionedOptions{ - Redis: AhoCorasickArgs{Addr: server.Addr(), Name: "overlay"}, - DeltaSearch: true, PollInterval: 20 * time.Millisecond, - }) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { _ = v.Close() }) - base := make([]string, 129) - for i := range base { - base[i] = fmt.Sprintf("word-%03d", i) - } - r, err := v.Replace(ctx, v.Status().ServingVersion, base) - if err != nil { - t.Fatal(err) - } - waitV3(t, v, r.Version) - if v.Status().DeltaSearch { - t.Fatal("large replacement used overlay") - } - r, err = v.AddMany(ctx, r.Version, []string{"she", "한국어"}) - if err != nil { - t.Fatal(err) - } - waitV3(t, v, r.Version) - if s := v.Status(); !s.DeltaSearch || s.DeltaKeywords != 2 { - t.Fatalf("status=%+v", s) - } - r, err = v.Remove(ctx, r.Version, "word-000") - if err != nil { - t.Fatal(err) - } - waitV3(t, v, r.Version) - if s := v.Status(); !s.DeltaSearch || s.DeltaKeywords != 3 { - t.Fatalf("status=%+v", s) - } - text := "SHE 한국어 word-000 word-001" - got, err := v.Find(ctx, text) - if err != nil || !reflect.DeepEqual(got, []string{"she", "한국어", "word-001"}) { - t.Fatal(got, err) - } - var stream []Match - if err = v.FindStream(ctx, strings.NewReader(strings.Repeat(text+" ", 300)), func(m Match) bool { stream = append(stream, m); return true }); err != nil { - t.Fatal(err) - } - all, err := v.FindMatches(ctx, strings.Repeat(text+" ", 300), nil) - if err != nil || !reflect.DeepEqual(stream, all) { - t.Fatal("stream parity", err) - } - deadline := time.After(5 * time.Second) - for v.Status().DeltaSearch { - select { - case <-deadline: - t.Fatal("compaction did not run") - case <-time.After(20 * time.Millisecond): - } - } - if got, err := v.Find(ctx, text); err != nil || !reflect.DeepEqual(got, []string{"she", "한국어", "word-001"}) { - t.Fatal(got, err) - } -} - -func TestVersionedOverlayCompactionRedisError(t *testing.T) { - ctx := context.Background() - server := miniredis.RunT(t) - v, err := OpenVersioned(ctx, &VersionedOptions{ - Redis: AhoCorasickArgs{Addr: server.Addr(), Name: "overlay-compact-error"}, - DeltaSearch: true, PollInterval: time.Hour, - }) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { _ = v.Close() }) - base := make([]string, 129) - for i := range base { - base[i] = fmt.Sprintf("word-%03d", i) - } - r, err := v.Replace(ctx, v.Status().ServingVersion, base) - if err != nil { - t.Fatal(err) - } - waitV3(t, v, r.Version) - r, err = v.Add(ctx, r.Version, "new-word") - if err != nil { - t.Fatal(err) - } - waitV3(t, v, r.Version) - current := v.current.Load() - if current.base == nil { - t.Fatal("expected an overlay") - } - ready := *current - ready.installed = time.Now().Add(-v3CompactDelay) - v.current.Store(&ready) - server.Close() - v.compactIfIdle(ctx) - if s := v.Status(); s.LastError == "" || s.ServingVersion != r.Version || !s.DeltaSearch { - t.Fatalf("failed compaction changed serving snapshot: %+v", s) - } -} diff --git a/pkg/acor/versioned_test.go b/pkg/acor/versioned_test.go index 44b9142..731963b 100644 --- a/pkg/acor/versioned_test.go +++ b/pkg/acor/versioned_test.go @@ -110,6 +110,41 @@ func TestVersionedLifecycle(t *testing.T) { t.Fatal(found, err) } } + +func TestVersionedSmallUpdateUsesSingleEngine(t *testing.T) { + ctx := context.Background() + server := miniredis.RunT(t) + v, err := OpenVersioned(ctx, &VersionedOptions{ + Redis: AhoCorasickArgs{Addr: server.Addr(), Name: "single-engine"}, + DeltaSearch: true, + PollInterval: 20 * time.Millisecond, + }) + if err != nil { + t.Fatal(err) + } + defer v.Close() + + r, err := v.Replace(ctx, v.Status().ServingVersion, []string{"stable"}) + if err != nil { + t.Fatal(err) + } + if err = v.WaitForVersion(ctx, r.Version); err != nil { + t.Fatal(err) + } + r, err = v.Add(ctx, r.Version, "new") + if err != nil { + t.Fatal(err) + } + if err = v.WaitForVersion(ctx, r.Version); err != nil { + t.Fatal(err) + } + if status := v.Status(); status.DeltaSearch || status.DeltaKeywords != 0 { + t.Fatalf("small update used delta search: %+v", status) + } + if got, err := v.FindSet(ctx, "stable new"); err != nil || !slices.Equal(got, []string{"stable", "new"}) { + t.Fatalf("small update search: %v (%v)", got, err) + } +} func TestVersionedSearchParity(t *testing.T) { ctx := context.Background() server := miniredis.RunT(t) diff --git a/scripts/benchmark-v3.sh b/scripts/benchmark-v3.sh index 2ab9588..c994028 100644 --- a/scripts/benchmark-v3.sh +++ b/scripts/benchmark-v3.sh @@ -6,8 +6,6 @@ set -eu repeats=${ACOR_V3_SCALE_REPEATS:-3} output=${ACOR_V3_SCALE_OUTPUT:-/tmp/acor-v3-results} counts=${ACOR_V3_SCALE_COUNTS:-"10000 100000 1000000"} -modes=${ACOR_V3_SCALE_MODES:-"baseline"} -compare=${ACOR_V3_DELTA_COMPARE:-0} mkdir -p "$output" binary=$(mktemp /tmp/acor-v3-test.XXXXXX) trap 'rm -f "$binary"' EXIT HUP INT TERM @@ -16,28 +14,13 @@ repeat=1 while [ "$repeat" -le "$repeats" ]; do for count in $counts; do for kind in shared diverse korean; do - for mode in $modes; do - case "$mode" in - baseline) delta=0 ;; - delta) delta=1 ;; - *) echo "invalid mode: $mode" >&2; exit 2 ;; - esac - if [ "$compare" = 1 ]; then - test_name=TestVersionedDeltaScale - result="$output/$count-$kind-$mode-$repeat.txt" - else - test_name=TestVersionedScale - result="$output/$count-$kind-$repeat.txt" - fi - ACOR_V3_SCALE_N=$count ACOR_V3_SCALE_KIND=$kind ACOR_V3_SCALE_DELTA=$delta \ - "$binary" -test.run="^$test_name\$" -test.v -test.timeout=15m > "$result" 2>&1 - echo "completed $count $kind $mode repeat $repeat" - done + result="$output/$count-$kind-$repeat.txt" + ACOR_V3_SCALE_N=$count ACOR_V3_SCALE_KIND=$kind \ + "$binary" -test.run='^TestVersionedScale$' -test.v -test.timeout=15m > "$result" 2>&1 + echo "completed $count $kind repeat $repeat" done done repeat=$((repeat + 1)) done -if [ "$compare" != 1 ]; then - "$binary" -test.run='^TestVersionedMillionSafety$' -test.v -test.timeout=15m \ - > "$output/million-safety.txt" 2>&1 -fi +"$binary" -test.run='^TestVersionedMillionSafety$' -test.v -test.timeout=15m \ + > "$output/million-safety.txt" 2>&1