Repository navigation
PROF-16213: Account CTimer table in NativeMem and gate thread registration #912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b507f77
d727893
83d5e21
0d93361
54689c5
9d581c5
20f2d28
f79c1cc
eb6b11f
ac310d7
ae8c8ed
3839410
e4ecdd1
08375d3
a24bc50
f95195e
404fc14
fd7482f
2de3fa9
688e368
08c964e
9de032e
3a00a33
ad06a06
73f0255
e389e30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,17 +14,32 @@ | |
| // per-category live byte gauges partition the total: sum(category) == total, | ||
| // with no double counting. | ||
| // | ||
| // These gauges track memory that is actually touched (and therefore resident), | ||
| // not address space that has merely been reserved. NM_CALLTRACE in particular | ||
| // counts the bytes LinearAllocator::alloc() has bump-allocated, NOT the | ||
| // capacity of the 8 MiB chunks backing them -- see linearAllocator.cpp. | ||
| // With the exceptions below, these gauges track memory that is actually touched | ||
| // (and therefore resident), not address space that has merely been reserved. | ||
| // NM_CALLTRACE in particular counts the bytes LinearAllocator::alloc() has | ||
| // bump-allocated, NOT the capacity of the 8 MiB chunks backing them -- see | ||
| // linearAllocator.cpp. | ||
| // | ||
| // Exceptions: the tid-indexed tables of CTimer (NM_CTIMER, | ||
| // pid_max * sizeof(int)) and PerfEvents (part of NM_PERF, | ||
| // pid_max * sizeof(PerfEvent), two cache lines per slot) are counted at their | ||
| // full calloc'd size. That memory is mostly untouched address space -- only the | ||
| // pages holding live tids become resident -- so for these two categories the | ||
| // gauge overstates RSS and should be read as an upper bound. NM_PERF's | ||
| // per-thread ring pages (2 pages each) are touched and resident. | ||
| // | ||
| // Consequently NM_CALLTRACE is no longer an "arena reserved" figure with | ||
| // CALLTRACE_STORAGE_BYTES as its used slice: both now count touched bytes, and | ||
| // their small difference is the call-trace hash tables (also bump-allocated), | ||
| // not chunk slack. Do not compute arena waste as the difference between them. | ||
| // DICTIONARY_ARENA_WASTE_BYTES remains a genuine nested waste figure for the | ||
| // DICTIONARY arena. None of these nested counters are summed in here. | ||
| // | ||
| // The exported per-category counter names (native_mem_{live,avg,max, | ||
| // chunk_overhead,post_flush_live,post_flush_max}_bytes.<category>, written by | ||
| // Recording::writeNativeMem()) derive from this table, and the set grows when | ||
| // a category is added, so consumers should match native_mem_*_bytes. counters | ||
| // by prefix rather than hard-code the category list. | ||
| #define DD_NATIVE_MEM_CATEGORY_TABLE(X) \ | ||
| X(CALLTRACE, "calltrace") \ | ||
| X(DICTIONARY, "dictionary") \ | ||
|
|
@@ -38,6 +53,7 @@ | |
| X(METHOD_MAP, "method_map") \ | ||
| X(LIVENESS, "liveness") \ | ||
| X(WALLCLOCK, "wallclock") \ | ||
| X(CTIMER, "ctimer") \ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Sphinx review — MEDIUM · Status — In-repo, the new category is exported end-to-end; what remains is verification outside this repo: consumers that hard-code the Finding — The new NM_CTIMER category changes the externally observable counter-name set: every JFR chunk now exports native_mem_bytes.ctimer (live/avg/max), and the category count grows from 13 to 14. In-repo consumers that enumerate DD_NATIVE_MEM_CATEGORY_TABLE are updated automatically, but downstream consumers of the native_mem counter series that hard-code the category list (agent-side metric extraction, dashboards, or alerting keyed on the fixed category names) will silently miss the new series or, if they validate the tag set, see an unexpected value. The PR description acknowledges this ('Consumers with a fixed category list need the new name') but no verification of such consumers exists in this repository, so the compatibility surface is unverified. Additionally, unlike NM_PERF (which reports ring pages that are mostly resident), the full tid-indexed table is largely untouched virtual address space, so the live gauge for ctimer overstates real RSS; this is documented. Evidence X(CTIMER, "ctimer") \Suggestion — Confirm with the agent/dashboard owners that native_mem_*_bytes consumers discover categories dynamically (or add the ctimer series to their fixed list) before merging, and document in ProfilingEngines.md that the ctimer gauge is allocated address space rather than resident RSS (already partially done in the PR body; mirror it in the NativeMem section of the doc). Author decision needed — confirm with metric/dashboard/alert owners that the new |
||
| X(MISC, "misc") | ||
|
|
||
| #define X_NM_ENUM(a, b) NM_##a, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Sphinx review — MEDIUM ·
ddprof-lib/src/main/cpp/ctimer_linux.cpp:123· Fixed ina24bc50cc— verified against the full gtest suiteFinding — The bound checks added as the safety net for a failed/empty table reject only tids at or above the bound; a negative tid passes
tid >= _max_timersandtid >= _max_eventsand indexes before the table. CTimer::registerThread (ctimer_linux.cpp:58) would CAS-write_timers[-k], CTimer::unregisterThread (line 129) would atomically load and CAS before the array, and PerfEvents::unregisterThread (perfEvents_linux.cpp:715/719) dereferences_events[negative]. The new comments explicitly claim these checks 'reject every tid' (ctimer_linux.cpp:140-142, perfEvents_linux.cpp:971-974), which is only true for tid >= 0. The new eventFor() does checktid < 0, so the PR itself treats negative tids as a real input class, but the register/unregister paths were not given the same half of the check.Evidence
Suggestion — Add the missing lower-bound half to all four one-sided checks (CTimer::registerThread ctimer_linux.cpp:58, CTimer::unregisterThread ctimer_linux.cpp:123, PerfEvents::registerThread, PerfEvents::unregisterThread perfEvents_linux.cpp:715), matching eventFor()'s
tid < 0guard.Anchor note: the bound check (123) sits outside the diff context of the reviewed head.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in a24bc50.
CTimer::registerThread(),CTimer::unregisterThread(),PerfEvents::registerThread()andPerfEvents::unregisterThread()all checktid < 0 || tid >= bound. Covered byNegativeTidIsRejectedinctimer_ut.cppandperfEvents_ut.cpp.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: the
PerfEventshalf is reverted in 688e368 and deferred to PROF-16359. TheCTimer::registerThread()/unregisterThread()checks stay, covered byNegativeTidIsRejectedinctimer_ut.cpp.