Skip to content

Add benchmarks for updating existing keys#145

Merged
cb1kenobi merged 1 commit intomainfrom
update-benchmarks
Sep 16, 2025
Merged

Add benchmarks for updating existing keys#145
cb1kenobi merged 1 commit intomainfrom
update-benchmarks

Conversation

@cb1kenobi
Copy link
Copy Markdown
Member

@cb1kenobi cb1kenobi commented Sep 16, 2025

Added some benchmarks for updating existing keys.

Also added permissions to benchmark CI workflow to make self hosted runner happier.

@github-actions
Copy link
Copy Markdown
Contributor

📊 Benchmark Results

encoding.bench.ts

Key encoding > ordered-binary keys - strings (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 24.41K ops/sec 40.97 36.82 431.528 0.574 12,205
🥈 rocksdb 2 4.63K ops/sec 216.173 197.765 1,536.701 0.909 2,313

Key encoding > ordered-binary keys - numbers (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 27.32K ops/sec 36.61 32.74 463.251 0.670 13,658
🥈 rocksdb 2 4.83K ops/sec 207.127 188.882 1,595.752 0.799 2,414

Key encoding > ordered-binary keys - mixed types (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 24.61K ops/sec 40.64 35.96 601.376 1.01 12,304
🥈 rocksdb 2 4.69K ops/sec 213.274 196.369 820.303 0.512 2,345

Value encoding > msgpack values - strings (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 16.00K ops/sec 62.50 56.77 641.883 0.818 8,000
🥈 rocksdb 2 4.20K ops/sec 237.89 220.56 777.639 0.494 2,102

Value encoding > msgpack values - numbers (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 25.78K ops/sec 38.79 35.07 709.409 0.716 12,891
🥈 rocksdb 2 4.71K ops/sec 212.451 190.004 3,168.21 1.32 2,354

Value encoding > msgpack values - arrays (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 9.60K ops/sec 104.219 94.70 881.951 0.870 4,798
🥈 rocksdb 2 3.50K ops/sec 285.499 262.034 1,006.555 0.597 1,752

Value encoding > msgpack values - small objects (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 5.51K ops/sec 181.605 159.678 1,135.86 1.89 2,754
🥈 rocksdb 2 2.62K ops/sec 380.969 347.061 1,151.595 0.670 1,313

Value encoding > msgpack values - large objects (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 628.40 ops/sec 1,591.335 1,455.205 5,375.051 3.26 315
🥈 rocksdb 2 617.44 ops/sec 1,619.599 1,448.876 3,288.273 1.97 309

get-sync.bench.ts

getSync() > random keys - small key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 20.10K ops/sec 49.76 41.90 4,014.47 1.97 10,048
🥈 rocksdb 2 4.47K ops/sec 223.527 192.959 11,069.535 6.32 2,237

get.bench.ts

get() > rocksdb - random vs sequential keys (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 sequential 1 4.11K ops/sec 243.408 226.748 768.307 0.609 2,055
🥈 random 2 3.97K ops/sec 251.87 231.507 1,536.222 0.894 1,986

get() > random keys - max 1978 lmdb key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 3.30K ops/sec 302.789 268.414 2,038.754 1.87 1,652

get() > rocksdb - async vs sync

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 sync 1 4.24K ops/sec 235.769 210.689 3,715.775 1.96 2,121
🥈 async 2 3.67K ops/sec 272.265 248.807 922.841 0.555 1,837

put-sync.bench.ts

putSync() > random keys - insert - small key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 2.09K ops/sec 478.434 445.206 674.31 0.308 1,046
🥈 lmdb 2 4.32 ops/sec 231,524.803 221,368.717 249,960.19 2.35 10.00

putSync() > random keys - update - small key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 2.04K ops/sec 490.292 457.04 943.999 0.601 1,020
🥈 lmdb 2 4.28 ops/sec 233,742.378 221,363.622 259,523.884 4.19 10.00

putSync() > random keys - insert - max 1978 lmdb key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 990.43 ops/sec 1,009.661 932.683 1,238.532 0.397 496
🥈 lmdb 2 4.14 ops/sec 241,567.331 233,183.247 257,202.991 2.91 10.00

putSync() > random keys - update - max 1978 lmdb key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 997.94 ops/sec 1,002.066 902.561 1,406.784 0.567 499
🥈 lmdb 2 4.18 ops/sec 239,372.366 228,158.068 256,771.718 2.83 10.00

putSync() > sequential keys - insert (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 601.63 ops/sec 1,662.14 459.175 355,608.81 139.125 301
🥈 lmdb 2 4.36 ops/sec 229,440.858 224,616.403 249,934.047 2.34 10.00

putSync() > put 100KB value (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 51.27 ops/sec 19,505.684 18,000.756 21,151.291 2.32 26.00
🥈 lmdb 2 3.21 ops/sec 311,239.455 282,738.992 338,012.504 4.01 10.00

putSync() > put 1MB value (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 5.19 ops/sec 192,597.557 186,448.456 208,796.297 2.50 10.00
🥈 lmdb 2 1.76 ops/sec 567,050.101 524,130.783 601,704.74 2.73 10.00

putSync() > get 10MB value (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 0.38 ops/sec 2,655,974.438 2,072,403.077 2,998,598.659 8.84 10.00
🥈 lmdb 2 0.27 ops/sec 3,714,690.974 3,130,258.342 4,019,306.404 5.82 10.00

put.bench.ts

put > small dataset (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 1.89K ops/sec 528.243 498.581 902.638 0.437 947
🥈 lmdb 2 4.02 ops/sec 248,492.965 237,216.978 268,393.317 2.69 10.00

put > async vs sync overhead

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 sync 1 2.06K ops/sec 484.708 462.174 848.872 0.314 1,032
🥈 async 2 1.84K ops/sec 543.681 501.221 956.496 0.384 920

ranges.bench.ts

getRange() > small range (100 records, 50 range)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 23.82K ops/sec 41.99 37.31 741.994 1.00 11,909
🥈 rocksdb 2 2.99K ops/sec 334.379 282.939 2,074.133 2.40 1,496

getRange() > full scan vs range scan

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb range scan 1 21.79K ops/sec 45.88 40.33 901.044 1.11 10,898
🥈 lmdb full scan 2 11.23K ops/sec 89.03 75.85 746.076 1.68 5,617
🥉 rocksdb range scan 3 3.00K ops/sec 333.307 289.519 1,846.331 1.88 1,501
rocksdb full scan 4 1.66K ops/sec 603.743 528.904 3,596.765 2.68 829

getKeys() > keys only (100 records, 50 range)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 48.54K ops/sec 20.60 16.44 3,228.864 2.09 24,272
🥈 rocksdb 2 4.94K ops/sec 202.52 181.735 1,131.392 1.15 2,469

Reverse iteration > reverse range (100 records, 50 range)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 555.82K ops/sec 1.80 1.19 7,028.369 7.30 277,908
🥈 rocksdb 2 2.97K ops/sec 337.018 296.615 1,430.297 1.53 1,484

Reverse iteration > rocksdb - reverse vs forward

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 forward 1 3.15K ops/sec 317.388 280.499 1,419.448 1.65 1,576
🥈 reverse 2 3.08K ops/sec 324.273 293.458 1,741.969 1.64 1,542

Range query patterns > prefix scan performance

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 31.23K ops/sec 32.02 28.57 1,555.901 1.22 15,616
🥈 rocksdb 2 3.32K ops/sec 301.56 265.729 2,740.585 2.34 1,659

Sparse data patterns > sparse - range over gaps

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 60.02K ops/sec 16.66 14.62 2,134.261 1.63 30,012
🥈 rocksdb 2 6.08K ops/sec 164.425 145.865 1,272.438 1.16 3,041

Sparse data patterns > sparse - prefix with gaps

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 121.63K ops/sec 8.22 6.75 3,541.012 3.02 60,817
🥈 rocksdb 2 12.26K ops/sec 81.58 71.09 2,726.462 1.55 6,129

remove-sync.bench.ts

removeSync() > random keys - small key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 12.44K ops/sec 80.39 69.38 824.916 1.84 6,220
🥈 rocksdb 2 2.59K ops/sec 386.255 370.363 726.114 0.381 1,296

removeSync() > sequential keys - small key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 12.68K ops/sec 78.89 69.99 888.749 1.32 6,338
🥈 rocksdb 2 2.56K ops/sec 390.814 374.658 618.566 0.275 1,280

removeSync() > rocksdb - random vs sequential keys (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 random 1 2.46K ops/sec 406.729 378.447 780.561 0.768 1,230
🥈 sequential 2 2.41K ops/sec 414.734 374.734 1,297.255 0.982 1,206

removeSync() > random keys - max 1978 lmdb key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 10.32K ops/sec 96.90 87.87 861.948 1.11 5,161
🥈 rocksdb 2 1.08K ops/sec 930.009 833.893 1,271.288 0.535 538

removeSync() > random access pattern (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 10.94K ops/sec 91.38 78.63 563.823 1.33 5,472
🥈 rocksdb 2 2.47K ops/sec 404.289 386.654 579.821 0.242 1,237

removeSync() > non-existent keys (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 11.89K ops/sec 84.10 78.52 462.069 0.433 5,946
🥈 rocksdb 2 2.59K ops/sec 386.134 363.221 610.784 0.274 1,295

transaction-sync.bench.ts

transaction sync > optimistic > simple put operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 660.96 ops/sec 1,512.948 1,414.732 4,935.009 1.86 331
🥈 lmdb 2 4.35 ops/sec 230,096.756 224,600.636 235,365.286 1.11 10.00

transaction sync > optimistic > batch operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 2.87K ops/sec 348.633 306.095 2,307.444 1.07 1,435
🥈 lmdb 2 368.65 ops/sec 2,712.593 2,062.568 5,292.118 3.17 185

transaction sync > optimistic > read-write operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 378.74 ops/sec 2,640.32 2,329.483 4,780.822 1.99 190
🥈 lmdb 2 4.38 ops/sec 228,508.41 222,622.126 239,729.393 1.68 10.00

transaction sync > optimistic > concurrent non-conflicting operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 667.38 ops/sec 1,498.394 1,423.818 3,243.657 1.21 334
🥈 lmdb 2 4.33 ops/sec 230,847.808 223,982.232 248,668.484 2.86 10.00

transaction sync > optimistic > rollback operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 15.49K ops/sec 64.55 58.97 552.721 0.541 7,746
🥈 rocksdb 2 5.16K ops/sec 193.907 173.414 1,020.798 0.779 2,579

transaction sync > optimistic > rocksdb - large transaction vs many small

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 2.77K ops/sec 360.762 299.048 972.311 1.04 1,386
🥈 rocksdb 2 660.85 ops/sec 1,513.207 1,391.66 4,700.34 2.05 331

transaction sync > optimistic > lmdb - large transaction vs many small

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 393.46 ops/sec 2,541.54 2,062.338 5,729.3 1.87 197
🥈 lmdb 2 4.33 ops/sec 231,121.567 210,845.935 251,849.146 3.83 10.00

transaction sync > optimistic > empty transaction overhead

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 793.63K ops/sec 1.26 1.08 1,214.442 0.598 396,818
🥈 rocksdb 2 112.33K ops/sec 8.90 7.86 2,229.505 1.77 56,169

transaction sync > optimistic > transaction with only reads (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 1.49K ops/sec 672.567 613.835 4,259.285 3.28 744
🥈 rocksdb 2 273.93 ops/sec 3,650.523 3,424.719 11,605.821 4.13 137

transaction sync > pessimistic > simple put operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 615.50 ops/sec 1,624.704 1,575.155 1,976.323 0.331 308
🥈 lmdb 2 4.33 ops/sec 230,826.957 218,367.532 251,887.74 2.93 10.00

transaction.bench.ts

transaction > optimistic > simple put operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 296.27 ops/sec 3,375.317 2,591.32 5,975.222 3.29 149
🥈 lmdb 2 3.74 ops/sec 267,025.588 245,407.471 281,117.171 2.89 10.00

transaction > optimistic > batch operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 2.18K ops/sec 458.315 378.193 585.913 0.283 1,091
🥈 lmdb 2 340.69 ops/sec 2,935.18 2,103.509 5,389.067 2.32 171

transaction > optimistic > read-write operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 209.33 ops/sec 4,777.105 4,010.047 7,257.844 2.66 105
🥈 lmdb 2 3.78 ops/sec 264,374.024 239,985.349 295,352.459 3.73 10.00

transaction > optimistic > concurrent non-conflicting operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 950.70 ops/sec 1,051.853 859.22 4,414.737 3.52 476
🥈 lmdb 2 319.44 ops/sec 3,130.498 2,151.349 10,049.842 3.99 160

transaction > optimistic > rollback operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 4.95K ops/sec 201.823 187.958 914.181 0.598 2,478
🥈 lmdb 2 339.89 ops/sec 2,942.13 2,108.562 5,299.196 2.18 171

transaction > optimistic > rocksdb - large transaction vs many small

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 1.67K ops/sec 598.38 486.422 1,008.154 0.778 836
🥈 rocksdb 2 299.33 ops/sec 3,340.838 2,825.995 8,228.138 3.62 150

transaction > optimistic > lmdb - large transaction vs many small

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 330.31 ops/sec 3,027.479 2,153.396 9,161.697 5.30 166
🥈 lmdb 2 3.80 ops/sec 262,859.428 242,307.083 303,686.906 4.70 10.00

transaction > optimistic > empty transaction overhead

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 40.50K ops/sec 24.69 18.41 336.325 0.412 20,250
🥈 rocksdb 2 36.39K ops/sec 27.48 17.27 4,537.143 3.36 18,195

transaction > optimistic > transaction with only reads (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 357.76 ops/sec 2,795.195 2,545.478 4,360.104 1.59 179
🥈 rocksdb 2 158.15 ops/sec 6,323.259 4,949.999 15,416.22 5.93 80.00

transaction > pessimistic > simple put operations (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 175.27 ops/sec 5,705.443 2,897.367 19,072.427 19.35 88.00
🥈 lmdb 2 3.80 ops/sec 263,160.664 247,872.747 281,332.347 2.34 10.00

worker-get-sync.bench.ts

Worker > random keys - small key size (100 records, 1 worker)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 15.29K ops/sec 65.38 58.07 1,460.344 0.770 7,648
🥈 rocksdb 2 3.59K ops/sec 278.192 229.259 1,529.293 1.06 1,798

Worker > random keys - small key size (100 records, 2 workers)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 13.49K ops/sec 74.13 61.80 4,515.042 2.47 6,746
🥈 rocksdb 2 3.46K ops/sec 289.43 236.482 2,935.474 1.58 1,728

Worker > random keys - small key size (100 records, 10 workers)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 7.44K ops/sec 134.465 118.558 2,583.994 1.14 3,719
🥈 rocksdb 2 1.68K ops/sec 597.003 498.829 2,905.253 2.00 838

worker-put-sync.bench.ts

putSync() > random keys - small key size (100 records, 1 worker)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 1.81K ops/sec 551.672 497.706 2,329.676 1.00 907
🥈 lmdb 2 4.02 ops/sec 248,598.462 230,620.727 268,681.278 3.15 10.00

putSync() > random keys - small key size (100 records, 2 workers)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 1.39K ops/sec 717.535 653.929 2,488.288 0.987 697
🥈 lmdb 2 2.12 ops/sec 472,695.181 434,333.644 493,121.376 2.63 10.00

putSync() > random keys - small key size (100 records, 10 workers)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 791.65 ops/sec 1,263.182 1,106.604 4,190.761 1.62 396
🥈 lmdb 2 1.00 ops/sec 1,001,076.382 901,803.673 1,108,384.44 4.90 10.00

Results from commit 7cdb31b

@cb1kenobi cb1kenobi requested a review from a team September 16, 2025 08:09
@cb1kenobi cb1kenobi marked this pull request as ready for review September 16, 2025 08:09
@heskew
Copy link
Copy Markdown
Member

heskew commented Sep 16, 2025

Haven't looked over here since you've been doing the benchmarks. I love the report. It might be neat (if possible) to have copilot (or claude via api?) summarize the results, also comparing against the target branch. E.g. Nice work Chris, rocksdb is still lagging lmdb in this area but this change improves on the baseline by n% meaning [some real world example]. 🤖 🙈

Copy link
Copy Markdown
Member

@kriszyp kriszyp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@cb1kenobi cb1kenobi merged commit 7d2104a into main Sep 16, 2025
13 checks passed
@cb1kenobi cb1kenobi deleted the update-benchmarks branch September 16, 2025 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants