ImGui's CalcWordWrapPosition() only cuts a word mid-word when it fits on
no line, i.e. when it is wider than the full line width. PrintTextWrapped
passes the leftover width for a glued continuation segment's first line,
so a continuation word wider than the leftover (but fitting on the next
full-width line) was being cut mid-word. Detect that case and move the
whole word to the next line instead.
There is a legitimate, if rare, way to get nonReentrantCount == 0 with
total != 0 — an outer zone that never terminated before the capture ended,
whose reentrant inner zone did terminate. The outer never contributes to
slz (no end event), but it did increment the stack count, so the inner one
is correctly recorded as a reentry.
The child calls display normalized hotness colors by the sum of two
independently tracked maxima, which can occur on different addresses.
The denominator could therefore exceed any real combined cost, so
nothing reached full heat and the color scale changed meaning when the
child calls display was toggled. Track the maximum of the per-address
sums instead.
Rows in the sampling statistics were only clickable when the symbol had
exclusive samples. In the "with children" accumulation mode this made
symbols which never directly executed, such as dispatchers or wrappers
with all cost in their callees, visible but completely inert, even
though the entry stacks window can now display how such symbols were
reached. Base the interactivity on the count shown in the current
accumulation mode. The popup menu items already disable themselves when
their data is not available.
The inline function expansion follows the same rule, so expanding such
a symbol now lists its inline functions with their inclusive counts
instead of showing an empty tree.
The find zone samples list shares the drawing code with the sampling
statistics window, which computed the percentage denominator from its
own state: the whole-trace sample count, or the statistics range
filter, if one was active. The find zone counts are scoped to the
matched zones, so the percentages mixed two meanings in one table: the
time column was relative to the zone selection while the count column
was relative to the whole trace, and changing the range filter in the
statistics window silently rescaled it.
Pass the denominator from the caller. Find zone sums its zone-scoped
counts, so both columns are now relative to the selection, and the
statistics window computes the same denominator as before.
The symbol disassembly tool scoped its cost data to the statistics
range filter. This is invisible UI state which the model cannot see, so
range-limited numbers were indistinguishable from whole-trace figures
and could silently change between tool calls. The other sampling tools
always report whole-trace data; do the same here.
The heuristic reconstruction picks the call stack from the samples
within the zone's time span. Context switch samples are always parked
at the scheduler, so for zones which spent their time blocked they
dominated the root selection and the reconstructed stack showed the
scheduler path instead of the zone's real call stack. A zone covering
only context switch samples now reconstructs nothing instead.
Context switch samples are excluded from the sampling statistics, but
the flame graph built from thread samples included them. Threads which
spend time blocked accumulated large scheduler towers which none of the
other sampling views show, and the flame graph totals did not
correspond to the statistics for the same trace. Filter the samples the
same way the trace load jobs do.
The per-symbol exclusive counts reported by the tool come from the
sampling statistics, which exclude context switch samples, but the
total time reference was computed from the full sample count. This
inflated the total and made every symbol look proportionally cheaper
to the model. Use the same denominator as the statistics window.
When displaying the hottest inline function's name in place of the base
symbol name, the symbol map lookup was dereferenced without checking
for a missing entry, crashing in release builds. Keep the base symbol
name when the inline symbol has no symbol data.
Several code paths read the per-symbol sample lists, symbol statistics
or child sample data without checking the readiness flags. These
structures are populated by background jobs during trace load, and the
flags are the only synchronization mechanism, so reading early races
the jobs and trips the readiness asserts in debug builds. The find zone
samples list checked a different flag than the data it reads requires,
and two symbol view conditions called the accessor before the readiness
check made elsewhere in the same function. The trace information window
performed no check at all, while it is typically open during loading.
The denominator includes samples with unresolved call stacks and
samples belonging to filtered-out rows, so describing it as the number
of samples attributable to the displayed symbols was overstating what
the code does.