Skip to content

perf(compressor): Improve string dictionary selection - #9762

Draft
lwwmanning wants to merge 2 commits into
developfrom
wm/string-dictionary-selection
Draft

perf(compressor): Improve string dictionary selection#9762
lwwmanning wants to merge 2 commits into
developfrom
wm/string-dictionary-selection

Conversation

@lwwmanning

@lwwmanning lwwmanning commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

String Dictionary selection now probes a small distributed sample before it builds an exact candidate. The old estimator missed profitable dictionaries when columns contained thousands of repeated strings. Samples above 75% distinct values reject Dictionary. An incomplete probe uses the existing estimator. An admitted candidate has explicit limits for values, value bytes, code bytes, and input bytes. The compressor compares the candidate's actual size and reuses the candidate if it wins.

The probe reads at most 8,192 rows and 1 MiB of values. String samples now compact their payload before size estimates, so unrelated retained bytes do not distort the score.

On seven local runs of the standard compression benchmark, Euro2016 stayed effectively neutral: write +0.01%, full materialization +0.46%, and size -0.14%. HashTags wrote 4.4% faster and used 2.1% fewer bytes, but full materialization was 10.9% slower. The benchmark expands Dictionary into flat strings. Engines that preserve Dictionary can retain the encoded form.

🤖 Generated with Codex

Signed-off-by: Will Manning <will@willmanning.io>
@lwwmanning lwwmanning added changelog/performance A performance improvement action/bench-compress Run only the compression benchmark on this PR labels Sep 3, 2026
@github-actions github-actions Bot removed the action/bench-compress Run only the compression benchmark on this PR label Sep 3, 2026
@codspeed-hq

codspeed-hq Bot commented Sep 3, 2026

Copy link
Copy Markdown

Merging this PR will regress 3 benchmarks

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 4 improved benchmarks
❌ 3 regressed benchmarks
✅ 2192 untouched benchmarks
⏩ 206 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime mul_u64_nonnull_neon 15.3 µs 21.1 µs -27.31%
WallTime multiply_shapes_neon[(16384, PerRowPerRow)] 17.2 µs 20.2 µs -14.58%
WallTime mul_i64_nonnull_neon 17.2 µs 20.1 µs -14.28%
WallTime arrow_checked_add_u32_neon[16384] 20.5 µs 12.7 µs +60.66%
WallTime mul_u32_nonnull_avx2 6.9 µs 5.9 µs +16.83%
WallTime mul_u32_nonnull_avx512 6.3 µs 5.6 µs +11.8%
Simulation allocate_drop_bytes[0] 520.2 ns 466 ns +11.62%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing wm/string-dictionary-selection (6ed06bd) with develop (265b705)

Open in CodSpeed

Footnotes

  1. 206 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Polar Signals Profiling Results

Latest Run

Status Commit Job Attempt Link
🟢 Done 2d35497 compress-bench 1 Explore Profiling Data

Powered by Polar Signals Cloud

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Benchmarks: Compression 📖

Commits: PR 2d35497e vs base 78f4d38c


vortex / vortex-file-compressed / ns (1.016x ➖, 0↑ 2↓)
name ns (PR / base / %diff)
compress time/Arade 1143608713 / 1215603812 / -5.9%
compress time/Bimbo 5003048286 / 5018243728 / -0.3%
compress time/CMSprovider 3913629876 / 3967096119 / -1.3%
compress time/Euro2016 693350612 / 509086549 / +36.2% 🔴
compress time/Food 430482231 / 433584645 / -0.7%
compress time/HashTags 909851785 / 907587690 / +0.2%
compress time/TPC-H l_comment canonical 1181212441 / 1188633662 / -0.6%
compress time/TPC-H l_comment chunked 1196472891 / 1173516349 / +2.0%
compress time/taxi 570596673 / 564884790 / +1.0%
compress time/wide table cols=100 chunks=1 rows=1000 8118458 / 8076756 / +0.5%
compress time/wide table cols=100 chunks=50 rows=1000 7955371 / 7930451 / +0.3%
compress time/wide table cols=1000 chunks=1 rows=1000 79139244 / 83741436 / -5.5%
compress time/wide table cols=1000 chunks=50 rows=1000 81904576 / 84174570 / -2.7%
compress time/wide table cols=10000 chunks=1 rows=1000 955742206 / 977690005 / -2.2%
compress time/wide table cols=10000 chunks=50 rows=1000 970515580 / 984025322 / -1.4%
decompress time/Arade 24794895 / 26821398 / -7.6%
decompress time/Bimbo 87385307 / 91391780 / -4.4%
decompress time/CMSprovider 75643015 / 79834024 / -5.2%
decompress time/Euro2016 30154262 / 15594588 / +93.4% 🔴
decompress time/Food 7188754 / 7263078 / -1.0%
decompress time/HashTags 112920738 / 107383616 / +5.2%
decompress time/TPC-H l_comment canonical 34679860 / 34750201 / -0.2%
decompress time/TPC-H l_comment chunked 34973027 / 35005949 / -0.1%
decompress time/taxi 14236487 / 14547466 / -2.1%
decompress time/wide table cols=100 chunks=1 rows=1000 2254470 / 2371697 / -4.9%
decompress time/wide table cols=100 chunks=50 rows=1000 2237859 / 2320215 / -3.5%
decompress time/wide table cols=1000 chunks=1 rows=1000 22581602 / 22794151 / -0.9%
decompress time/wide table cols=1000 chunks=50 rows=1000 22495049 / 22797743 / -1.3%
decompress time/wide table cols=10000 chunks=1 rows=1000 245298413 / 261231574 / -6.1%
decompress time/wide table cols=10000 chunks=50 rows=1000 252918839 / 249126611 / +1.5%
vortex / vortex-file-compressed / bytes (1.000x ➖, 0↑ 0↓)
name bytes (PR / base / %diff)
vortex-file-compressed size/Arade 144460980 / 144460980 / +0.0%
vortex-file-compressed size/Bimbo 461842908 / 461842908 / +0.0%
vortex-file-compressed size/CMSprovider 415192460 / 415192460 / +0.0%
vortex-file-compressed size/Euro2016 159857604 / 157458700 / +1.5%
vortex-file-compressed size/Food 41581832 / 41581624 / +0.0%
vortex-file-compressed size/HashTags 176094956 / 177840324 / -1.0%
vortex-file-compressed size/TPC-H l_comment canonical 163480008 / 163453384 / +0.0%
vortex-file-compressed size/TPC-H l_comment chunked 163480008 / 163453384 / +0.0%
vortex-file-compressed size/taxi 51475172 / 51475172 / +0.0%
vortex-file-compressed size/wide table cols=100 chunks=1 rows=1000 932744 / 932744 / +0.0%
vortex-file-compressed size/wide table cols=100 chunks=50 rows=1000 932744 / 932744 / +0.0%
vortex-file-compressed size/wide table cols=1000 chunks=1 rows=1000 9309944 / 9309944 / +0.0%
vortex-file-compressed size/wide table cols=1000 chunks=50 rows=1000 9309944 / 9309944 / +0.0%
vortex-file-compressed size/wide table cols=10000 chunks=1 rows=1000 93117944 / 93117944 / +0.0%
vortex-file-compressed size/wide table cols=10000 chunks=50 rows=1000 93117944 / 93117944 / +0.0%
vortex / vortex-file-compressed / ratio (1.008x ➖, 0↑ 2↓)
name ratio (PR / base / %diff)
vortex:parquet-zstd ratio compress time/Arade 0.39232065 / 0.422323541 / -7.1%
vortex:parquet-zstd ratio compress time/Bimbo 0.3546728 / 0.359891495 / -1.5%
vortex:parquet-zstd ratio compress time/CMSprovider 0.508679584 / 0.519639452 / -2.1%
vortex:parquet-zstd ratio compress time/Euro2016 0.455272923 / 0.336424772 / +35.3% 🔴
vortex:parquet-zstd ratio compress time/Food 0.468021386 / 0.478484283 / -2.2%
vortex:parquet-zstd ratio compress time/HashTags 0.3740726 / 0.373748323 / +0.1%
vortex:parquet-zstd ratio compress time/TPC-H l_comment canonical 0.320175554 / 0.325255001 / -1.6%
vortex:parquet-zstd ratio compress time/TPC-H l_comment chunked 0.325554192 / 0.320162404 / +1.7%
vortex:parquet-zstd ratio compress time/taxi 0.418978123 / 0.415949938 / +0.7%
vortex:parquet-zstd ratio compress time/wide table cols=100 chunks=1 rows=1000 1.54868802 / 1.56758805 / -1.2%
vortex:parquet-zstd ratio compress time/wide table cols=100 chunks=50 rows=1000 1.56055505 / 1.54942098 / +0.7%
vortex:parquet-zstd ratio compress time/wide table cols=1000 chunks=1 rows=1000 1.22341148 / 1.29900243 / -5.8%
vortex:parquet-zstd ratio compress time/wide table cols=1000 chunks=50 rows=1000 1.26506052 / 1.33206454 / -5.0%
vortex:parquet-zstd ratio compress time/wide table cols=10000 chunks=1 rows=1000 1.27950012 / 1.32194529 / -3.2%
vortex:parquet-zstd ratio compress time/wide table cols=10000 chunks=50 rows=1000 1.2854234 / 1.33639435 / -3.8%
vortex:parquet-zstd ratio decompress time/Arade 0.0353060124 / 0.0379094802 / -6.9%
vortex:parquet-zstd ratio decompress time/Bimbo 0.0454663062 / 0.0477945758 / -4.9%
vortex:parquet-zstd ratio decompress time/CMSprovider 0.0396448827 / 0.0417641901 / -5.1%
vortex:parquet-zstd ratio decompress time/Euro2016 0.0720825979 / 0.0373875379 / +92.8% 🔴
vortex:parquet-zstd ratio decompress time/Food 0.0327030852 / 0.0328329079 / -0.4%
vortex:parquet-zstd ratio decompress time/HashTags 0.167791905 / 0.157557532 / +6.5%
vortex:parquet-zstd ratio decompress time/TPC-H l_comment canonical 0.0527165313 / 0.0525715192 / +0.3%
vortex:parquet-zstd ratio decompress time/TPC-H l_comment chunked 0.0530124971 / 0.0528529152 / +0.3%
vortex:parquet-zstd ratio decompress time/taxi 0.0509608715 / 0.0513671232 / -0.8%
vortex:parquet-zstd ratio decompress time/wide table cols=100 chunks=1 rows=1000 0.925075101 / 0.981653727 / -5.8%
vortex:parquet-zstd ratio decompress time/wide table cols=100 chunks=50 rows=1000 0.955360753 / 0.986521202 / -3.2%
vortex:parquet-zstd ratio decompress time/wide table cols=1000 chunks=1 rows=1000 0.806534034 / 0.802895187 / +0.5%
vortex:parquet-zstd ratio decompress time/wide table cols=1000 chunks=50 rows=1000 0.799812305 / 0.844769188 / -5.3%
vortex:parquet-zstd ratio decompress time/wide table cols=10000 chunks=1 rows=1000 0.819084867 / 0.867655515 / -5.6%
vortex:parquet-zstd ratio decompress time/wide table cols=10000 chunks=50 rows=1000 0.836630663 / 0.823209908 / +1.6%
vortex:parquet-zstd size/Arade 0.559895285 / 0.559895285 / -0.0%
vortex:parquet-zstd size/Bimbo 1.20109789 / 1.20109789 / -0.0%
vortex:parquet-zstd size/CMSprovider 1.1016338 / 1.1016338 / -0.0%
vortex:parquet-zstd size/Euro2016 1.29987673 / 1.28037012 / +1.5%
vortex:parquet-zstd size/Food 1.16477351 / 1.16476769 / +0.0%
vortex:parquet-zstd size/HashTags 1.31908715 / 1.33216131 / -1.0%
vortex:parquet-zstd size/TPC-H l_comment canonical 1.03234293 / 1.03217481 / +0.0%
vortex:parquet-zstd size/TPC-H l_comment chunked 1.03234293 / 1.03217481 / +0.0%
vortex:parquet-zstd size/taxi 0.931110481 / 0.931110481 / -0.0%
vortex:parquet-zstd size/wide table cols=100 chunks=1 rows=1000 1.00036465 / 1.00036465 / -0.0%
vortex:parquet-zstd size/wide table cols=100 chunks=50 rows=1000 1.00036465 / 1.00036465 / -0.0%
vortex:parquet-zstd size/wide table cols=1000 chunks=1 rows=1000 0.998492064 / 0.998492064 / -0.0%
vortex:parquet-zstd size/wide table cols=1000 chunks=50 rows=1000 0.998492064 / 0.998492064 / -0.0%
vortex:parquet-zstd size/wide table cols=10000 chunks=1 rows=1000 0.998690905 / 0.998690905 / -0.0%
vortex:parquet-zstd size/wide table cols=10000 chunks=50 rows=1000 0.998690905 / 0.998690905 / -0.0%
vortex / parquet / ns (1.004x ➖, 0↑ 0↓)
name ns (PR / base / %diff)
parquet_rs-zstd compress time/Arade 2914984753 / 2878370951 / +1.3%
parquet_rs-zstd compress time/Bimbo 14106095216 / 13943768617 / +1.2%
parquet_rs-zstd compress time/CMSprovider 7693703457 / 7634324338 / +0.8%
parquet_rs-zstd compress time/Euro2016 1522933996 / 1513225514 / +0.6%
parquet_rs-zstd compress time/Food 919791795 / 906162774 / +1.5%
parquet_rs-zstd compress time/HashTags 2432286633 / 2428339166 / +0.2%
parquet_rs-zstd compress time/TPC-H l_comment canonical 3689264926 / 3654466982 / +1.0%
parquet_rs-zstd compress time/TPC-H l_comment chunked 3675188097 / 3665378362 / +0.3%
parquet_rs-zstd compress time/taxi 1361877009 / 1358059559 / +0.3%
parquet_rs-zstd compress time/wide table cols=100 chunks=1 rows=1000 5242152 / 5152346 / +1.7%
parquet_rs-zstd compress time/wide table cols=100 chunks=50 rows=1000 5097783 / 5118332 / -0.4%
parquet_rs-zstd compress time/wide table cols=1000 chunks=1 rows=1000 64687348 / 64465958 / +0.3%
parquet_rs-zstd compress time/wide table cols=1000 chunks=50 rows=1000 64743603 / 63191060 / +2.5%
parquet_rs-zstd compress time/wide table cols=10000 chunks=1 rows=1000 746965309 / 739584315 / +1.0%
parquet_rs-zstd compress time/wide table cols=10000 chunks=50 rows=1000 755016271 / 736328558 / +2.5%
parquet_rs-zstd decompress time/Arade 702285342 / 707511627 / -0.7%
parquet_rs-zstd decompress time/Bimbo 1921979466 / 1912178912 / +0.5%
parquet_rs-zstd decompress time/CMSprovider 1908014601 / 1911542493 / -0.2%
parquet_rs-zstd decompress time/Euro2016 418329290 / 417106578 / +0.3%
parquet_rs-zstd decompress time/Food 219818832 / 221213364 / -0.6%
parquet_rs-zstd decompress time/HashTags 672980844 / 681551777 / -1.3%
parquet_rs-zstd decompress time/TPC-H l_comment canonical 657855499 / 661008119 / -0.5%
parquet_rs-zstd decompress time/TPC-H l_comment chunked 659712878 / 662327685 / -0.4%
parquet_rs-zstd decompress time/taxi 279361137 / 283205776 / -1.4%
parquet_rs-zstd decompress time/wide table cols=100 chunks=1 rows=1000 2437067 / 2416022 / +0.9%
parquet_rs-zstd decompress time/wide table cols=100 chunks=50 rows=1000 2342423 / 2351916 / -0.4%
parquet_rs-zstd decompress time/wide table cols=1000 chunks=1 rows=1000 27998325 / 28389946 / -1.4%
parquet_rs-zstd decompress time/wide table cols=1000 chunks=50 rows=1000 28125410 / 26986949 / +4.2%
parquet_rs-zstd decompress time/wide table cols=10000 chunks=1 rows=1000 299478629 / 301077524 / -0.5%
parquet_rs-zstd decompress time/wide table cols=10000 chunks=50 rows=1000 302306442 / 302628295 / -0.1%
vortex / parquet / bytes (1.000x ➖, 0↑ 0↓)
name bytes (PR / base / %diff)
parquet size/Arade 258014282 / 258014282 / +0.0%
parquet size/Bimbo 384517292 / 384517292 / +0.0%
parquet size/CMSprovider 376887911 / 376887911 / +0.0%
parquet size/Euro2016 122979049 / 122979049 / +0.0%
parquet size/Food 35699500 / 35699500 / +0.0%
parquet size/HashTags 133497590 / 133497590 / +0.0%
parquet size/TPC-H l_comment canonical 158358238 / 158358238 / +0.0%
parquet size/TPC-H l_comment chunked 158358238 / 158358238 / +0.0%
parquet size/taxi 55283635 / 55283635 / +0.0%
parquet size/wide table cols=100 chunks=1 rows=1000 932404 / 932404 / +0.0%
parquet size/wide table cols=100 chunks=50 rows=1000 932404 / 932404 / +0.0%
parquet size/wide table cols=1000 chunks=1 rows=1000 9324004 / 9324004 / +0.0%
parquet size/wide table cols=1000 chunks=50 rows=1000 9324004 / 9324004 / +0.0%
parquet size/wide table cols=10000 chunks=1 rows=1000 93240004 / 93240004 / +0.0%
parquet size/wide table cols=10000 chunks=50 rows=1000 93240004 / 93240004 / +0.0%
vortex / arrow-ipc / ns (1.012x ➖, 1↑ 1↓)
name ns (PR / base / %diff)
arrow-ipc compress time/Arade 283601688 / 283124715 / +0.2%
arrow-ipc compress time/Bimbo 1853753085 / 1805985194 / +2.6%
arrow-ipc compress time/CMSprovider 1428978670 / 1448092556 / -1.3%
arrow-ipc compress time/Euro2016 100312997 / 97345952 / +3.0%
arrow-ipc compress time/Food 74057542 / 71491525 / +3.6%
arrow-ipc compress time/HashTags 290528515 / 290755120 / -0.1%
arrow-ipc compress time/TPC-H l_comment canonical 2109177941 / 2069531998 / +1.9%
arrow-ipc compress time/TPC-H l_comment chunked 2152997765 / 2089599965 / +3.0%
arrow-ipc compress time/taxi 187119659 / 180601124 / +3.6%
arrow-ipc compress time/wide table cols=100 chunks=1 rows=1000 364620 / 411289 / -11.3% 🟢
arrow-ipc compress time/wide table cols=100 chunks=50 rows=1000 411609 / 417651 / -1.4%
arrow-ipc compress time/wide table cols=1000 chunks=1 rows=1000 4961917 / 5202057 / -4.6%
arrow-ipc compress time/wide table cols=1000 chunks=50 rows=1000 5069024 / 5173896 / -2.0%
arrow-ipc compress time/wide table cols=10000 chunks=1 rows=1000 57185916 / 56116668 / +1.9%
arrow-ipc compress time/wide table cols=10000 chunks=50 rows=1000 56061682 / 55294932 / +1.4%
arrow-ipc decompress time/Arade 184352202 / 190348060 / -3.1%
arrow-ipc decompress time/Bimbo 595654308 / 596907848 / -0.2%
arrow-ipc decompress time/CMSprovider 687804302 / 695064906 / -1.0%
arrow-ipc decompress time/Euro2016 96534467 / 96254705 / +0.3%
arrow-ipc decompress time/Food 64351693 / 65713114 / -2.1%
arrow-ipc decompress time/HashTags 205840308 / 209774262 / -1.9%
arrow-ipc decompress time/TPC-H l_comment canonical 1033190010 / 1032576724 / +0.1%
arrow-ipc decompress time/TPC-H l_comment chunked 1044718996 / 1037703467 / +0.7%
arrow-ipc decompress time/taxi 74021627 / 73788312 / +0.3%
arrow-ipc decompress time/wide table cols=100 chunks=1 rows=1000 432495 / 391398 / +10.5% 🔴
arrow-ipc decompress time/wide table cols=100 chunks=50 rows=1000 429830 / 400160 / +7.4%
arrow-ipc decompress time/wide table cols=1000 chunks=1 rows=1000 4357045 / 4141306 / +5.2%
arrow-ipc decompress time/wide table cols=1000 chunks=50 rows=1000 4407610 / 4087640 / +7.8%
arrow-ipc decompress time/wide table cols=10000 chunks=1 rows=1000 53664311 / 50399242 / +6.5%
arrow-ipc decompress time/wide table cols=10000 chunks=50 rows=1000 53133931 / 49595736 / +7.1%
vortex / arrow-ipc / bytes (1.000x ➖, 0↑ 0↓)
name bytes (PR / base / %diff)
arrow-ipc size/Arade 691765162 / 691765162 / +0.0%
arrow-ipc size/Bimbo 3279590114 / 3279590114 / +0.0%
arrow-ipc size/CMSprovider 2422259682 / 2422259682 / +0.0%
arrow-ipc size/Euro2016 360582666 / 360582666 / +0.0%
arrow-ipc size/Food 255782338 / 255782338 / +0.0%
arrow-ipc size/HashTags 704785810 / 704785810 / +0.0%
arrow-ipc size/TPC-H l_comment canonical 4852929378 / 4852929378 / +0.0%
arrow-ipc size/TPC-H l_comment chunked 4852929378 / 4852929378 / +0.0%
arrow-ipc size/taxi 482329690 / 482329690 / +0.0%
arrow-ipc size/wide table cols=100 chunks=1 rows=1000 1257290 / 1257290 / +0.0%
arrow-ipc size/wide table cols=100 chunks=50 rows=1000 1257290 / 1257290 / +0.0%
arrow-ipc size/wide table cols=1000 chunks=1 rows=1000 12568506 / 12568506 / +0.0%
arrow-ipc size/wide table cols=1000 chunks=50 rows=1000 12568506 / 12568506 / +0.0%
arrow-ipc size/wide table cols=10000 chunks=1 rows=1000 125752506 / 125752506 / +0.0%
arrow-ipc size/wide table cols=10000 chunks=50 rows=1000 125752506 / 125752506 / +0.0%

Signed-off-by: Will Manning <will@willmanning.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog/performance A performance improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant