Repository navigation
Add frame-level stack transforms to stacks - #10
Merged
Merged
Conversation
This was referenced Sep 23, 2026
lhotari
added this pull request to stack #14
September 23, 2026 20:16
lhotari
removed this pull request from stack #14
September 23, 2026 20:17
--include/--exclude decide which intervals a slice keeps, but most of every Java stack is structure that says nothing about the wait: nine Netty event-loop frames before the first application frame, and five to ten lock, park or monitor frames under the one that names the wait. stacks gains transforms that change what a kept interval's stack looks like: - --trim-root removes the longest root-side run of matching frames, --root-at starts the stack at its root-most match ([no application frame] when there is none, or unchanged with --root-at-unmatched keep), --leaf-at cuts below the leaf-most match, --collapse-leaf replaces the leaf-side wait machinery by the frame that entered it (or a category such as [lock] or [monitor] with --collapse-leaf-label category), --hide removes frames anywhere, --canonical-names removes generated-class addresses, and --thread-frame name|pool starts each line with the thread or its pool. Each REGEX option has a -from FILE form. - They apply in that fixed order after the filters, which still see the untransformed stack. Lines that transform alike merge, so no total changes, and without a transform the output is byte-identical. - Every -from option, the filters' included, takes preset:NAME, a bundled pattern list: jvm-infra, jvm-wait-machinery and jvm-idle, each with a header stating its purpose and caveats. stacks --list-presets prints them. - --collapsed-input FILE applies the same filters and transforms to any collapsed file, such as the converter's CPU view, normalising its _[j]-style markers and slashed class names; weights keep their unit. - The --summary file gains a transforms object: each option's patterns with their source, lines and weight-averaged depth before and after, and the [no application frame] weight and share. On the Pulsar broker fixtures every row of the spec's reference table is reproduced exactly, e.g. the busy off-CPU slice goes from 164 lines at a mean depth of 23.0 to 78 lines at 4.1 with --root-at and --collapse-leaf, and the CPU view from 9,839 lines at 28.9 to 4,925 at 9.6. The new testFixtureAcceptance task checks them when given -PjonoffcpuFixtures=DIR.
lhotari
force-pushed
the
stacks-transforms
branch
from
September 23, 2026 20:22
d3af0b7 to
1abc90a
Compare
lhotari
added this pull request to stack #15
September 23, 2026 20:22
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bottom of the 0.5.0 correlator stack (GitHub stack #15; spec:
stacks-transforms.md). Based onmain, which has the picocli command line from #8.What changes
stackstransforms that change a kept interval's Java stack, never which intervals are kept:--trim-root,--root-at(+--root-at-unmatched bucket|keep),--leaf-at,--collapse-leaf(+--collapse-leaf-label frame|category),--hide,--canonical-names,--thread-frame none|name|pool. Each REGEX option also has a-from FILEform.--package-names/--thread-frameas display. Filters still match the untransformed stack. Lines that transform alike merge, so totals never change. With no transform, the output is byte-identical to before.preset:jvm-infra,preset:jvm-wait-machinery,preset:jvm-idlework in every-fromoption, including--include-from/--exclude-from.stacks --list-presetsprints them with their caveat headers (e.g. musl symbolization,WorkerThread::run).--collapsed-input FILEruns any collapsed file (e.g. the converter's CPU view) through the same filters and transforms. It strips_[j]/_[i]/_[0]/_[1]markers and turns slashed class names into dotted ones. Weights keep their unit. Options that need profile data are refused.--summarygains atransformsobject: patterns with their sources,linesBefore/linesAfter,framesBefore/framesAfter, and thenoApplicationFrameweight and share.testFixtureAcceptance -PjonoffcpuFixtures=DIR. The fixtures are recordings kept outside the repo, so the task is skipped without the property.Verification
./gradlew spotlessCheck :jonoffcpu-correlator:check -PjonoffcpuFixtures=…/jonoffcpu-plans/fixturespasses.--collapsed-inputand off-CPU busy slice via--exclude-from preset:jvm-idle --exclude <bookkeeper take>:--hide preset:jvm-infra--trim-root preset:jvm-infra--collapse-leaf preset:jvm-wait-machinery--root-at '^org\.apache\.'StackTransformsTestcovers the spec's unit cases: merging with intervals and nanos added,--excludeseeing trimmed frames, the[no application frame]bucket, canonical names, pool frames, category labels, collapsed-input normalisation, presets and totals under every transform combined.Spec deviations to note
A;B;C;x.App.m;Dwith--trim-root '^(A|C)$'→ unchanged" contradicts its own rule.Amatches, so the root-side run[A]is trimmed, givingB;C;x.App.m;D. The implementation follows the rule, which is also what reproduces the reference table; the test documents both cases.--collapse-leaf-label categorykeeps the entry frame itself when no category applies (e.g.CompletableFuture$Signaller.block); the spec lists no category for that case.