Skip to content

lz4.c: faster extDict compression (branchless match selection) - #1967

Merged
Cyan4973 merged 1 commit into
devfrom
extdict_speed
Oct 28, 2026
Merged

Cyan4973 merged 1 commit into
devfrom
extdict_speed

Conversation

@Cyan4973

@Cyan4973 Cyan4973 commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

In extDict mode, dictionary and prefix candidates alternate unpredictably on small blocks : with gcc, choosing between them was a frequently mispredicted branch. The match pointer is now selected without branch, relative to dictEnd or source (it remains within its buffer : base can be NULL). clang already compiled it without branch. Output is byte-identical.

lz4 -b1 -D (64 KB dictionary, CDict path), silesia 32 MB, gcc 11, Zen 4 :

block dev PR
4 KB 300 MB/s 387 MB/s (+29%)
16 KB 292 MB/s 395 MB/s (+35%)
64 KB 377 MB/s 421 MB/s (+12%)
256 KB 443 MB/s 439 MB/s (-1%)
1 MB 465 MB/s 442 MB/s (-5%)
4 MB 473 MB/s 446 MB/s (-5.7%)

Beyond 64 KB, no candidate can be in the dictionary : the branch was well predicted there. Switching to prefix mode past 64 KB (future PR) would remove this cost.
Acceleration 3 : +12% to +28% (4-64 KB). gcc 15 : +29% to +35% (4-16 KB), -2.6% at 1 MB. clang 22 : neutral (within 1%). No dictionary : unchanged.

@Cyan4973 Cyan4973 self-assigned this Oct 27, 2026
In extDict mode, each candidate is either in the dictionary or in the prefix.
Small blocks see both kinds alternate unpredictably : with gcc, this branch
missed often (perf, 16 KB blocks : 0.26 misses per byte, 0.11 in prefix mode).
The match pointer is now selected without branch, in the match search and in
the test of the next position, relative to dictEnd or source : it remains within
its buffer (base can be NULL, when the address of source equals startIndex).
lowLimit is set only once a match is found.
clang already compiled it without branch. Output is unchanged (byte-identical).

lz4 -b1 -D (64 KB dictionary, CDict path), silesia 32 MB, gcc 11, Zen 4 :
- 4 KB blocks : 300 -> 387 MB/s (+29%)
- 16 KB : 292 -> 395 MB/s (+35%)
- 64 KB : 377 -> 421 MB/s (+12%)
- 256 KB : -1% ; 1 MB : 465 -> 442 MB/s (-5%) ; 4 MB : 473 -> 446 MB/s (-5.7%)
  (beyond 64 KB, no candidate can be in the dictionary : the branch was well predicted)
acceleration 3 : +12% to +28% from 4 to 64 KB.
gcc 15 : +29% to +35% for 4-16 KB, -2.6% at 1 MB. clang 22 : neutral (within 1%).
No dictionary : unchanged.
@Cyan4973
Cyan4973 merged commit 7430740 into dev Oct 28, 2026
106 checks passed
@Cyan4973
Cyan4973 deleted the extdict_speed branch October 28, 2026 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant