google / google/snappy

Question about inlining three small helpers in GCC 10/12 AArch64 shared builds

Open
#251 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
6.6k
Forks
1.1k
Avg merge
3d 5h
Merged PRs (30d)
4

Description

### Background

Hello, while evaluating shared-library decompression performance on AArch64, I noticed that GCC 10 and GCC 12 do not automatically inline the following three small helpers in the branchless decompression path:

- `MemCopy64(ptrdiff_t, const void*, size_t)`
- `ClearDeferred(const void**, size_t*, uint8_t*)`
- `DeferMemCopy(const void**, size_t*, const void*, size_t)`

This is specific to the shared-library build. The GCC inline report says that the function bodies can be overwritten at link time, and the final libsnappy.so contains calls through the PLT. GCC does inline them in a non-PIC static build.

Clang provides a useful comparison: on the same AArch64 machine, with the same unmodified source and shared-build settings, Clang 12 automatically inlines or eliminates all three calls at both O2 and O3.

I understand that optimizing around compiler-specific code generation may not be a priority for Snappy. I am sharing the measurements mainly to ask whether a small, standard C++ source annotation would be reasonable here. If this is outside the project's scope, that guidance would also be helpful.

### Performance results

I tested adding ordinary C++ `inline` to these helper definitions:

```diff
-void MemCopy64(ptrdiff_t dst, const void* src, size_t size) {
+inline void MemCopy64(ptrdiff_t dst, const void* src, size_t size) {
(void)dst;
(void)src;
(void)size;
}

-void ClearDeferred(const void** deferred_src, size_t* deferred_length,
+inline void ClearDeferred(const void** deferred_src, size_t* deferred_length,
uint8_t* safe_source) {
*deferred_src = safe_source;
*deferred_length = 0;
}

-void DeferMemCopy(const void** deferred_src, size_t* deferred_length,
+inline void DeferMemCopy(const void** deferred_src, size_t* deferred_length,
const void* src, size_t length) {
*deferred_src = src;
*deferred_length = length;
}
```

Performance was measured on a physical HiSilicon AArch64 server running openEuler 22.03 LTS-SP3, using GCC 10.3.1 with BUILD_SHARED_LIBS=ON.

The main flat-buffer decompression path and the two external data sets became about **12% to 16% faster**.The validation path became about **45% to 49% faster** because one of the removed calls invokes an empty helper.

Representative median throughput results are shown below. `Before` is the unmodified GCC build and `after` is the same build with the three `inline` annotations.

Each cell uses the format `before → after (improvement)`:

| Workload | GCC O2: before → after | GCC O3: before → after |
|---|---:|---:|
| `BM_UFlatMedley` | 978 → 1115 MB/s (**+14.0%**) | 983 → 1106 MB/s (**+12.5%**) |
| `BM_UValidateMedley` | 1353 → 1957 MB/s (**+44.6%**) | 1326 → 1979 MB/s (**+49.2%**) |
| Silesia dataset | 1009 → 1170 MB/s (**+16.0%**) | 1031 → 1171 MB/s (**+13.5%**) |
| `itemdata` dataset | 843 → 948 MB/s (**+12.4%**) | 842 → 949 MB/s (**+12.7%**) |

### Question
Given that this optimization is motivated by GCC-specific code generation, would adding ordinary inline to these three implementation helpers be something the project would consider?The change does not modify any public header, although these implementation-detail helper symbols no longer appear as out-of-line symbols in the resulting GCC shared library.

I would appreciate the maintainers' guidance before preparing any PR. Thank you for taking the time to review this.

Contributor guide

Open the contributing guide

Research direction

Locate the definitions and call sites for MemCopy64, ClearDeferred, and DeferMemCopy, then review how the shared-library AArch64 build handles them under GCC. Run BM_UFlatMedley and BM_UValidateMedley with the Silesia and itemdata datasets to compare the reported before-and-after behavior. Done means the project has guidance or an accepted change that preserves the measured performance benefit without affecting the public API.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
performance
Issue type
Refactor
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.