Skip to content

feat(nativemem): instrument remaining allocation sites - #724

Merged
jbachorik merged 4 commits into
mainfrom
native-mem-counters
Aug 13, 2026
Merged

feat(nativemem): instrument remaining allocation sites#724
jbachorik merged 4 commits into
mainfrom
native-mem-counters

Conversation

@rkennke

@rkennke rkennke commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Extends the categorized native-memory accounting from #669 to eight allocation sites that weren't yet instrumented:

  • Recording::_method_map -> new NM_METHOD_MAP category
  • LivenessTracker::_table -> new NM_LIVENESS category
  • UnwindFailures, ThreadInfo's two maps -> NM_THREAD_LOCAL
  • Lookup::_vtable_receiver_cache -> NM_JFR_BUFFERS
  • CallTraceStorage's two working buffers -> NM_CALLTRACE
  • wall-clock's thread-reservoir vector -> NM_MISC (capacity-based gauge, not allocator-wrapped, since ReservoirSampler is hard-coded to the default-allocator std::vector)

Adds CountingAllocator<T, Category> (ddprof-lib/src/main/cpp/countingAllocator.h): a stateless C++11 allocator wrapping ::operator new/delete that reports exact per-node byte counts via STL's allocator-rebinding, used for the STL-container sites. The two raw-malloc sites (UnwindFailures, LivenessTracker) get direct record()/setLive() calls instead.

Also fixes CodeCache::setDwarfTable(): the DWARF/SFrame parsers build their FrameDesc table with capacity-doubling malloc/realloc, so the incoming buffer is typically larger than the stored length. memoryUsage()'s formula was length * sizeof(FrameDesc), silently undercounting real memory whenever capacity > length. setDwarfTable() now shrinks the buffer to its exact size via realloc before storing it, which both corrects the formula and gives back the doubling slack to the allocator.

Test fixture fix: NativeMemTest's SetUp()/TearDown() used to zero all live gauges unconditionally via NativeMem::reset(). This is safe most of the time, but UnwindFailures is a genuine class-static object (UnwindStats::_unwind_failures) constructed before main() and destructed at real process exit; if its constructor's record() runs before the test and its destructor's matching decrement runs after TearDown() already zeroed the category, the decrement underflows and trips assert(updated >= 0). Fixed by snapshotting the pre-test baseline and restoring it in TearDown() instead of assuming zero is a safe baseline to leave in place.

Test plan

  • ./gradlew :ddprof-lib:compileRelease — clean, all 66 sources
  • Full gtest suite covering every touched subsystem (flightRecorder_result_ut, methodInfo_hash_ut, methodMapId_ut, lineNumberTableCopy_ut, test_callTraceStorage, stress_callTraceStorage, profiler_null_calltrace_buffer_ut, threadInfo_ut, livenessTracker_ut, wallClockCounters_ut, codeCache_ut, sframe_ut, dwarf_ut, nativeMem_ut) — all pass

🤖 Generated with Claude Code

…iveness table, thread info, call-trace buffers)

Extends the NM_* categorized native-memory accounting (#669) to eight
previously-uninstrumented allocation sites: Recording::_method_map and
LivenessTracker::_table get new NM_METHOD_MAP/NM_LIVENESS categories;
UnwindFailures, ThreadInfo's two maps, Lookup::_vtable_receiver_cache,
CallTraceStorage's two working buffers, and wall-clock's thread-reservoir
vector are folded into existing categories. Adds a stateless
CountingAllocator<T, Category> that wraps ::operator new/delete and
reports exact per-node byte counts via STL's allocator-rebinding, used
for the STL-container sites; raw-malloc sites (UnwindFailures,
LivenessTracker) get direct record()/setLive() calls.

Also fixes CodeCache::setDwarfTable() to shrink the DWARF/SFrame
FrameDesc table to its exact length via realloc, correcting
memoryUsage()'s length-based formula and eliminating the parser's
capacity-doubling slack from real RSS.

Test fixture fix: NativeMemTest's SetUp()/TearDown() used to zero all
live gauges unconditionally, which underflowed UnwindFailures's
destructor decrement (a real static-duration object accounted for
outside the test) at process exit. Snapshot and restore the pre-test
baseline instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@rkennke
rkennke requested a review from a team as a code owner August 7, 2026 18:15
@dd-octo-sts

dd-octo-sts Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Scan-Build Report

User:runner@runnervmvrwv9
Working Directory:/home/runner/work/java-profiler/java-profiler/ddprof-lib/src/test/make
Command Line:make -j4 all
Clang Version:Ubuntu clang version 18.1.3 (1ubuntu1)
Date:Thu Aug 13 07:38:12 2026

Bug Summary

Bug TypeQuantityDisplay?
All Bugs1
Logic error
Dereference of null pointer1

Reports

Bug Group Bug Type ▾ File Function/Method Line Path Length
Logic errorDereference of null pointerprofiler.hfindLibraryByAddress52313

@datadog-prod-us1-6

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1118c13363

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@@ -1,4 +1,6 @@
#include "countingAllocator.h"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add Datadog headers to touched files

This commit touches files that still do not satisfy the repository copyright rule: threadInfo.h, threadInfo.cpp, and unwindStats.h still lack a Datadog header, and several modified files with existing 2025 Datadog headers were not updated to the current year. Please add/update the current-year Datadog headers before landing.

AGENTS.md reference: AGENTS.md:L372-L374

Useful? React with 👍 / 👎.

Comment thread ddprof-lib/src/main/cpp/wallClock.h Outdated
@dd-octo-sts

dd-octo-sts Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

CI Test Results

Run: #31678457724 | Commit: f8d9ca1 | Duration: 14m 34s (longest job)

All 32 test jobs passed

Status Overview

JDK glibc-aarch64/debug glibc-amd64/debug musl-aarch64/debug musl-amd64/debug
8 - - -
8-ibm - - -
8-j9 - -
8-librca - -
8-orcl - - -
11 - - -
11-j9 - -
11-librca - -
17 - -
17-graal - -
17-j9 - -
17-librca - -
21 - -
21-graal - -
21-librca - -
25 - -
25-graal - -
25-librca - -

Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled

Summary: Total: 32 | Passed: 32 | Failed: 0


Updated: 2026-08-13 07:54:05 UTC

@dd-octo-sts

dd-octo-sts Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

All 40 integration tests passed

📊 Dashboard · 👷 Pipeline · 📦 496b265b

jbachorik and others added 2 commits August 11, 2026 10:21
…e shrink-to-fit

Add NM_THREAD_INFO/NM_WALLCLOCK categories, track thread-name heap bytes,
shrink dwarf/sframe tables to exact size at the source, and add
CountingAllocator unit tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Address PR #724 review feedback: add missing Datadog headers to
threadInfo.cpp and unwindStats.h; update stale 2025 headers to
2025, 2026 in callTraceHashTable.h, callTraceStorage.{cpp,h},
flightRecorder.h, stress_callTraceStorage.cpp, test_callTraceStorage.cpp.
@jbachorik
jbachorik merged commit 9010c4c into main Aug 13, 2026
117 checks passed
@jbachorik
jbachorik deleted the native-mem-counters branch August 13, 2026 09:36
@github-actions github-actions Bot added this to the 1.50.0 milestone Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants