Skip to content

Add java_cpu_alloc scenario for the Datadog java-profiler - #155

Open
jbachorik wants to merge 7 commits into
mainfrom
jbachorik/java-cpu-alloc-scenario
Open

Add java_cpu_alloc scenario for the Datadog java-profiler#155
jbachorik wants to merge 7 commits into
mainfrom
jbachorik/java-cpu-alloc-scenario

Conversation

@jbachorik

Copy link
Copy Markdown

Summary

  • Adds scenarios/java_cpu_alloc/, the first prof-correctness scenario for the Datadog java-profiler (PROF-15290).
  • Multi-stage Dockerfile builds jfr2pprof (btraceio/jafar, pinned to the v0.26.1 release) from source, downloads the java-profiler native agent (v1.45.0) from its GitHub release, compiles a small deterministic workload, runs it under the agent to record a .jfr, then converts it to pprof via jfr2pprof --config datadog.yaml.
  • Includes datadog.yaml, the jfr2pprof mapping for the Datadog java-profiler's JFR events (datadog.ExecutionSample, datadog.MethodSample, datadog.ObjectSample, datadog.HeapLiveObject), covering cpu-time, wall-time, allocation, and live-heap.
  • The workload runs two threads: CpuBurner (busy-spins, dominates CPU samples) and AllocGenerator (batches allocations with a park, dominates allocation samples), so expected_profile.json can assert distinct, non-overlapping method-qualified folded stacks per thread.
  • Only cpu-samples/alloc-samples are asserted here; wall-time and live-heap are mapped but not exercised by this workload (see caveats documented in datadog.yaml).

While building this, found and reported a real jfr2pprof bug (frame.format was parsed but never applied to Function.Name, collapsing all frames of a class into one node) — filed as btraceio/jafar#105 and fixed upstream in v0.26.1, which this scenario is pinned to.

Test plan

  • TEST_SCENARIOS="java_cpu_alloc" TEST_RUN_SECS=10 go test -v -run TestScenarios ./... passes locally: both cpu-samples and alloc-samples assertions succeed at 0% error.

Builds jfr2pprof from source, runs the profiler agent against a
deterministic cpu/alloc workload, and converts the recording via the
datadog.yaml mapping to validate cpu-samples and alloc-samples.
@jbachorik jbachorik added the AI AI-assisted work label Jul 2, 2026
jbachorik added 6 commits July 2, 2026 11:43
Makes the workload's purpose explicit and avoids the sole fully-qualified
name (LockSupport) in favor of a proper import.
Matches the other prof-correctness profilers (ddprof's latest-rc tag,
dd-trace-py/-rb/-js's unpinned/master dependencies), which default to
latest and only pin a specific build as an explicit override.
Drops the from-source Gradle build stage now that jfr2pprof ships inside
jafar-tools, resolvable via jbang.
@jbachorik
jbachorik marked this pull request as ready for review July 2, 2026 16:03
@jbachorik
jbachorik requested a review from a team as a code owner July 2, 2026 16:03

@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: dbb7d0b120

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# jfr2pprof has no --help; running it bare still resolves/caches the jbang
# dependency, it just exits non-zero after printing its usage string.
RUN jbang trust add https://github.com/btraceio/ \
&& (jbang jafar-tools-latest@btraceio jfr2pprof || true) \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don't swallow JBang resolution failures

When the JBang warm-up fails for anything other than the expected no-args usage exit (for example a catalog/Maven resolution error, alias change, or trust prompt), || true still lets the Docker image build as if jfr2pprof were cached. The scenario then fails later in run.sh when it needs the uncached tool, which makes the build-time caching guarantee unreliable; make this step distinguish the expected usage exit from dependency-resolution failures.

Useful? React with 👍 / 👎.

@kaahos kaahos 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.

it looks good to me, thanks!

I would just recommend maybe adding a short README describing the test to match the architecture of the other scenarios and also adding the scenario to the CI?

java:
  uses: ./.github/workflows/test.yml
  with:
    test_scenarios: java.*
  secrets: inherit

@r1viollet

Copy link
Copy Markdown
Collaborator

Alternative approach : https://github.com/DataDog/prof-correctness/pull/156/changes
what do we prefer ?

@jbachorik

Copy link
Copy Markdown
Author

@r1viollet did you do completeness check on that jfr parser in go? Also, I would rather stick with the devil I know - we are using the jafar parser in other parts, it is a complete JFR parser, very well tested and with extraordinary performance.

I thought the reason to use the go JFR parser was to do more by-event comparisons, but since the result is again pprof files the difference to converting jfr to pprof by those two tools is almost none?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI AI-assisted work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants