Repository navigation
Conversation
MemCopy64 (both overloads), ClearDeferred and DeferMemCopy are used only by DecompressBranchless but are ordinary external-linkage functions. When snappy is built as a shared library, GCC must assume that semantic interposition can replace them at run time, so it neither inlines them nor calls them directly: every call in the hot loop goes through the PLT. In a -O2 -fPIC shared build with GCC 11, DecompressBranchless contains 14 such calls. The cost is more than the calls themselves. DecompressBranchless passes the addresses of its deferred_src and deferred_length locals to ClearDeferred and DeferMemCopy, so as long as those calls are opaque the two variables have to live on the stack and are stored and reloaded on every tag. With the helpers inlined they stay in registers. In the same build the two instantiations of DecompressBranchless shrink from 451 to 274 instructions, and the number of instructions that access the stack drops from 104 to 40. Declaring the helpers inline removes all of the calls and stops exporting the four symbols from libsnappy.so. This is what was agreed in google#251, and replaces the stale google#259. Declaring them static produces an identical instruction sequence for DecompressBranchless in this build. Measured with the existing snappy_benchmark (no new benchmark is needed), built with GCC 11, -O2, BUILD_SHARED_LIBS=ON on x86-64 and pinned to one core. Throughput is the median of three interleaved rounds of five repetitions. The hardware counters are per benchmark iteration, taken as the difference between runs of 1200 and 200 iterations so that the one-off setup cancels out: throughput instructions cycles branches BM_UFlatMedley +42% -21% -30% -32% BM_UValidateMedley +52% -37% -34% -49% Branch mispredictions are essentially unchanged (-2% on BM_UFlatMedley), so the gain comes from executing fewer instructions and branches rather than from better prediction. End to end, Apache Gluten with the Velox backend on TPC-H SF300 (3 executors x 4 cores), two builds differing only in giving these helpers internal linkage, median of three rounds: q8 -7.6% q9 -5.5% q5 -4.3% combined -5.7% The slowest patched round is faster than the fastest baseline round for every query. snappy_unittest passes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: Lipeng Zhu <lipeng.zhu@intel.com> Co-authored-by: Wangyang Guo <wangyang.guo@intel.com>
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mark
MemCopy64(both overloads),ClearDeferred, andDeferMemCopyasinline. These helpers are used only byDecompressBranchless.In a GCC 11
-O2 -fPICshared-library build, semantic interposition prevents GCC from inlining these helpers, leaving 14 PLT calls in the decompression hot path. The opaque calls also forcedeferred_srcanddeferred_lengthonto the stack instead of keeping them in registers.With the helpers inlined:
DecompressBranchlessinstantiations drops from 451 to 274.This follows the approach discussed in #251 and supersedes the stale PR #259. It also complements the AArch64 GCC 10 results reported in #251 with measurements on x86-64 GCC 11.
Performance Results
1. Snappy microbenchmarks
Measured using the existing
snappy_benchmarkwith GCC 11,-O2, andBUILD_SHARED_LIBS=ONon x86-64, pinned to one core.Throughput is the median of three interleaved rounds of five repetitions. Hardware counters are measured per benchmark iteration by taking the difference between runs of 1200 and 200 iterations and dividing by 1000, which eliminates one-time setup overhead.
Branch mispredictions are essentially unchanged (-2% on BM_UFlatMedley), so the gain comes from executing fewer instructions and branches.
2. End-to-end TPC-H performance
Tested with Apache Gluten + Velox on TPC-H SF300 (3 executors × 4 cores), using GCC 13 builds differing only in the helper-linkage change.
For these Gluten builds, the helpers were given internal linkage using
static. In the GCC 11 shared-library build above,staticandinlineproduce identical instruction sequences forDecompressBranchless.Results are medians of three rounds. For all three queries, the slowest patched run was faster than the fastest baseline run.
3. Correctness
snappy_unittestpasses.