Repository navigation
Conversation
…OF-16484) MallocFootprint::headerBytes() took the smallest address stride between 16 fresh 48-byte blocks as usable + header. That holds only if two blocks are adjacent; with freed same-size chunks scattered between live ones (tcache, fastbins), none are, the derived header exceeds the sanity bound, and the probe fell back to 0. The NM_* overhead gauges then undercounted every small allocation for the process lifetime, and mallocFootprint_ut flaked on arm64 CI runs. glibc is now recognised by malloc_usable_size: a glibc chunk's usable size holds the request and is congruent to size_t modulo 2 * size_t (a free chunk too small to split is handed out whole, so it may be larger). Size-class allocators and sanitizers report a multiple of 2 * size_t for the probe sizes 48, 96 and 112 and keep the stride probe, as does any non-glibc build; the glibc header is then sizeof(size_t). Tests: a fragmented heap where the stride probe alone misses the header while the full probe returns sizeof(size_t); the layout rule on fixed values, including an unsplit chunk; a plain glibc build (no preload, no malloc checking, no sanitizer) is recognised. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
More details
Usable-size recognition survived a focused glibc fragmentation check, supporting the replacement of heap-dependent stride detection. The Google Test suite could not run because Google Test was unavailable.
🤖 Bits Code Review · Commit 3d57e13
CI Test ResultsRun: #42294125733 | Commit:
Status Overview
Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled Summary: Total: 32 | Passed: 32 | Failed: 0 Updated: 2026-11-06 21:46:49 UTC |
Scan-Build Report
Bug Summary
Reports
|
|||||||||||||||||||||||||||||||||||||||||||||||||
What does this PR do?:
Makes
MallocFootprint::headerBytes()independent of heap state on glibc.malloc_usable_size. A glibc chunk's usable size holds the request and is congruent tosize_tmodulo2 * size_t(a free chunk too small to split is handed out whole, so it may be larger). Then the header issizeof(size_t). Size-class allocators (jemalloc, tcmalloc, mimalloc), sanitizers and glibc's debug modes report other sizes and keep the stride probe, as does any non-glibc build.Motivation:
PROF-16484.
MallocFootprintTest.OverheadFractionCollapsesWithAllocationSizefailed on arm64 merge-queue runs of unrelated PRs (Deny direct gradlew calls from agent sessions (PROF-16469) #937 twice, Keep .knowledgebase writes to cairn: file-tool hook and frontmatter check (PROF-16469) #946 twice) withprobed per-chunk header = 0.Additional Notes:
probeHeaderBytes(),glibcChunks(),glibcUsable()andstrideHeaderBytes()are public so tests can call them in a prepared heap state; production code still uses the cachedheaderBytes(). A gtest friend would pull gtest into a production header.malloc_usable_sizebelongs to the allocator in force;of()already relied on that.of()stays 8 bytes low for them;allocatorExposesOverhead()comment says sanitizers make the probe yield 0; under ASan the stride probe yields 16;< 1 %assertion would fail on arm64 kernels with 16 or 64 KiB pages.How to test the change?:
gtestRelease_mallocFootprint_ut,gtestDebug_…,gtestAsan_…(x64)FragmentedHeapStillYieldsGlibcHeader: after freeing every other one of 512 blocks, the stride probe alone misses the header, the full probe returnssizeof(size_t)For Datadog employees:
credentials of any kind, I've requested a security review (run the
dd:platform-security-reviewskill, or file a request via the PSEC review form).
bewairealso runs automatically on every PR.🤖 Generated with Claude Code