Skip to content

Remove legacy DirectByteBuffer-based OTEP context storage (Phase 3) - #696

Merged
rkennke merged 12 commits into
mainfrom
remove-legacy-dbb-context-storage
Jul 31, 2026
Merged

Remove legacy DirectByteBuffer-based OTEP context storage (Phase 3)#696
rkennke merged 12 commits into
mainfrom
remove-legacy-dbb-context-storage

Conversation

@rkennke

@rkennke rkennke commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Phase 3 of the OTEP context-storage migration: dd-trace-java PR #11899 has landed and migrated onto the all-native context write API (setTraceContext/clearTraceContext/setContextValue/clearContextValue), so java-profiler was the last consumer of the legacy DirectByteBuffer-based path (ThreadContext, OtelContextStorage, ContextStorageMode, ContextSetter, ScopeStack), which carried a virtual-thread use-after-free risk.
  • Deletes the DBB conduit classes and their JNI backing (initializeContextTLS0), removes deprecated JavaProfiler APIs (setContext, clearContext, setContextAttribute, getThreadContext, contextStorageMode, etc.), and adds package-private test-only native read accessors (testGetSpanId, testGetRootSpanId, testReadTraceId, testReadContextAttribute, testIsContextValid) as the read oracle for tests.
  • Ports all Java tests, JMH benchmarks, and the chaos harness onto the all-native API; replaces ReapplyContextAntagonist/VirtualThreadContextCascadeAntagonist (whose premise was the DBB carrier-cache UAF) with a new ReapplyContextValueAntagonist exercising equivalent contention against the all-native record.
  • Adds ContextValueCacheTest to preserve the Dictionary-exhaustion/hash-collision coverage previously carried by the deleted TagContextTest.
  • Rewrites doc/architecture/TLSContext.md and deletes the now-superseded phase 1/2 design docs.

Test plan

  • ddprof-lib native (C++) and Java compile cleanly
  • ddprof-test-tracer, ddprof-stresstest (main/jmh/chaos source sets) compile cleanly
  • Targeted context tests pass: AllNativeContextTest, AllNativeContextSamplingTest, ContextValueCacheTest, MaxContextSlotsTest, PrecheckTest, WallclockMitigationsCombinedTest, ThreadFilterSmokeTest, QueueTimeTest, ContendedWallclockSamplesTest, WriteStackTracesAfterClassUnloadTest
  • Full ddprof-test:testDebug suite: 236 tests, 4 failures — all confirmed pre-existing/unrelated (thread-churn lifecycle timeouts, a flaky retried vtable-frame test, a wall-clock timing assertion), none touching context/tracing code
  • ContextCombinedBenchmark and TracedParallelWork JMH benchmarks execute without exceptions against the all-native API
  • Grep sweep confirms no dangling references to ThreadContext, OtelContextStorage, ContextStorageMode, ContextSetter, ScopeStack outside history

🤖 Generated with Claude Code

dd-trace-java PR #11899 has migrated onto the all-native context API
(setTraceContext/clearTraceContext/setContextValue/clearContextValue), so
java-profiler was the last consumer of the DirectByteBuffer-based
ThreadContext/OtelContextStorage path, which carried a virtual-thread
use-after-free risk. Deletes the DBB conduit and its Java/native/test/
benchmark/chaos surface, replacing coverage with equivalents against the
all-native path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 29, 2026 10:49
@rkennke
rkennke requested a review from a team as a code owner July 29, 2026 10:49

@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: 895586cc92

ℹ️ 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".

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Phase 3 of the OTEP context-storage migration: removes the legacy DirectByteBuffer-based context conduit and its APIs/JNI, fully standardizing java-profiler (tests/benchmarks/chaos harness included) on the all-native context write API (setTraceContext/clearTraceContext/setContextValue/clearContextValue) to eliminate the virtual-thread stale-buffer/UAF risk and simplify maintenance.

Changes:

  • Deletes the DBB conduit subsystem (ThreadContext, ScopeStack, OtelContextStorage, ContextStorageMode, ContextSetter) and related deprecated JavaProfiler APIs/JNI (initializeContextTLS0, etc.).
  • Updates Java tests, tracer test harness, JMH benchmarks, and chaos antagonists to use the all-native API; adds ContextValueCacheTest to preserve prior cache/eviction coverage.
  • Rewrites context/TLS documentation to reflect the new all-native model and removes superseded phase-plan/design docs.

Reviewed changes

Copilot reviewed 42 out of 42 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
doc/plans/2026-07-09-phase2-dd-trace-java-migration.md Removes phase-2 plan doc (superseded by completed migration).
doc/plans/2026-07-02-all-native-context-storage-design.md Removes design note now superseded by the implemented solution.
doc/architecture/TLSContext.md Updates architecture doc to describe all-native context writes and new invariants.
ddprof-test/src/test/java/com/datadoghq/profiler/wallclock/WallclockMitigationsCombinedTest.java Switches wallclock test to setTraceContext/clearTraceContext.
ddprof-test/src/test/java/com/datadoghq/profiler/wallclock/PrecheckTest.java Updates precheck tests to all-native context API; removes DBB-reset dependency.
ddprof-test/src/test/java/com/datadoghq/profiler/ScopeStackTest.java Deletes pure-Java ScopeStack unit test along with removed implementation.
ddprof-test/src/test/java/com/datadoghq/profiler/queue/QueueTimeTest.java Migrates queue-time test to all-native context API.
ddprof-test/src/test/java/com/datadoghq/profiler/OtelContextStorageTest.java Deletes tests for removed storage-mode selection (OtelContextStorage).
ddprof-test/src/test/java/com/datadoghq/profiler/memleak/WriteStackTracesAfterClassUnloadTest.java Removes resetThreadContext() cleanup now that DBB context is gone.
ddprof-test/src/test/java/com/datadoghq/profiler/MaxContextSlotsTest.java Drops ThreadContext slot-count assertion; keeps native-vs-Java constant check.
ddprof-test/src/test/java/com/datadoghq/profiler/filter/ThreadFilterSmokeTest.java Uses setTraceContext instead of deprecated setContext.
ddprof-test/src/test/java/com/datadoghq/profiler/ContextValueCacheTest.java Adds focused unit coverage for ContextValueCache eviction/limits/clear behavior.
ddprof-test/src/test/java/com/datadoghq/profiler/context/TagContextTest.java Deletes large DBB-based tag/context integration test (replaced by new tests).
ddprof-test/src/test/java/com/datadoghq/profiler/context/OtelContextStorageModeTest.java Deletes OTEL storage-mode tests tied to removed DBB storage selection.
ddprof-test/src/test/java/com/datadoghq/profiler/context/CarrierContextStorageTest.java Deletes carrier-scoped ThreadContext test (mode no longer exists).
ddprof-test/src/test/java/com/datadoghq/profiler/context/AllNativeContextTest.java Ports read oracle from ThreadContext DBB reads to new native test* accessors.
ddprof-test/src/test/java/com/datadoghq/profiler/context/AllNativeContextSamplingTest.java Updates sampling test narrative/assertions for “self-initializing on first write”.
ddprof-test/src/test/java/com/datadoghq/profiler/AbstractProfilerTest.java Removes resetThreadContext() from common stop path.
ddprof-test-tracer/src/main/java/com/datadoghq/profiler/context/Tracing.java Updates tracer bridge to call setTraceContext.
ddprof-test-tracer/src/main/java/com/datadoghq/profiler/context/ContextExecutor.java Removes DBB TLS priming (setContext(0,0)) now that first write initializes TLS.
ddprof-stresstest/src/jmh/java/com/datadoghq/profiler/stresstest/scenarios/throughput/ThreadContextBenchmark.java Removes DBB-focused benchmark suite.
ddprof-stresstest/src/jmh/java/com/datadoghq/profiler/stresstest/scenarios/throughput/ContextCombinedBenchmark.java Narrows perf-guard benchmark to the shipping all-native activate/deactivate cycle.
ddprof-stresstest/src/jmh/java/com/datadoghq/profiler/stresstest/scenarios/counters/TracedParallelWork.java Removes ContextSetter usage; writes tags via setContextValue.
ddprof-stresstest/src/chaos/README.md Updates chaos scenarios list to new all-native antagonist(s).
ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/VirtualThreadContextCascadeAntagonist.java Removes stale-carrier UAF antagonist tied to DBB path.
ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/ReapplyContextValueAntagonist.java Adds new all-native contention antagonist around per-slot set/clear + activation churn.
ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/ReapplyContextAntagonist.java Removes DBB reapply-by-id/bytes antagonist tied to deleted APIs.
ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/Main.java Updates antagonist wiring to new names/classes.
ddprof-stresstest/README.md Removes ThreadContext benchmark docs; updates benchmark listing.
ddprof-stresstest/build.gradle.kts Updates chaos compile-only note to reflect removal of ThreadContext usage.
ddprof-lib/src/main/java/com/datadoghq/profiler/ThreadContext.java Deletes legacy DBB-backed per-thread context implementation.
ddprof-lib/src/main/java/com/datadoghq/profiler/ScopeStack.java Deletes legacy DBB snapshot/restore stack.
ddprof-lib/src/main/java/com/datadoghq/profiler/OtelContextStorage.java Deletes legacy carrier/thread storage selection and reflective CarrierThreadLocal usage.
ddprof-lib/src/main/java/com/datadoghq/profiler/ContextStorageMode.java Deletes legacy storage-mode enum.
ddprof-lib/src/main/java/com/datadoghq/profiler/ContextSetter.java Deletes legacy DBB wrapper used by tests/benchmarks.
ddprof-lib/src/main/java/com/datadoghq/profiler/OTelContext.java Updates javadoc to reference JavaProfiler#setContextValue instead of ThreadContext.
ddprof-lib/src/main/java/com/datadoghq/profiler/JavaProfiler.java Removes deprecated DBB APIs; keeps all-native write API; adds test-only native read accessors; clears value-cache on dictionary reset.
ddprof-lib/src/main/java/com/datadoghq/profiler/ContextValueCache.java Moves dictionary registration native into ContextValueCache now that ThreadContext is gone.
ddprof-lib/src/main/cpp/wallClock.cpp Updates commentary around validity/context presence after deactivation.
ddprof-lib/src/main/cpp/threadLocalData.h Updates comments for record/sidecar contiguity now that DBB exposure is removed.
ddprof-lib/src/main/cpp/otel_context.h Removes static_assert message referencing deleted Java constants.
ddprof-lib/src/main/cpp/javaApi.cpp Removes initializeContextTLS0; adds all-native primitives + copyContextTags + ContextValueCache registration + test-only read JNI.
Comments suppressed due to low confidence (2)

ddprof-lib/src/main/cpp/javaApi.cpp:1064

  • testGetRootSpanId0 reads the LRS sidecar without checking record->valid. This can race with detach/attach mutations and return inconsistent data. Add an acquire load of record->valid and return 0 when invalid.
Java_com_datadoghq_profiler_JavaProfiler_testGetRootSpanId0(JNIEnv* env, jclass unused) {
  ProfiledThread* thrd = ProfiledThread::current();
  if (thrd == nullptr) {
    return 0;
  }
  u32* enc = thrd->getOtelTagEncodingsPtr();
  u64* lrs = reinterpret_cast<u64*>(enc + DD_TAGS_CAPACITY);
  return (jlong)*lrs;
}

ddprof-lib/src/main/cpp/javaApi.cpp:1095

  • testReadContextAttribute0 reads attrs_data without checking record->valid and builds the return value via a NUL-terminated char buffer + NewStringUTF. That can race with a detach/attach write (torn reads) and it will truncate at embedded NUL bytes / mis-decode non-modified UTF-8. Gate the read on an acquire load of record->valid and build the String from a byte[] using StandardCharsets.UTF_8.
  OtelThreadContextRecord* record = thrd->getOtelContextRecord();
  int targetKey = slot + 1;
  int size = record->attrs_data_size;
  uint8_t* d = record->attrs_data;
  int pos = 0;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ddprof-lib/src/main/cpp/javaApi.cpp
@rkennke
rkennke marked this pull request as draft July 29, 2026 10:58
@datadog-datadog-prod-us1

This comment has been minimized.

…Writer removal

dd-trace-java's DatadogProfiler still depends on ContextSetter.offsetOf()/size()
(pure-Java attribute-slot resolution, no DBB/JNI) per its Phase 2 migration
(DataDog/dd-trace-java#11899). Deleting the class outright in Phase 3 broke that
consumer; restore just the two pure-Java methods it uses.

BufferWriter/BufferWriter8/BufferWriter9 lost their only caller (ThreadContext)
in Phase 3 but were left behind as dead code, along with the Java-9
versioned-sources/multi-release-jar wiring and sourceCompatibility javadoc
exemption that existed solely to support them. Remove all of it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

ddprof-lib/src/main/cpp/javaApi.cpp:1107

  • testReadContextAttribute0 builds a C-string and returns it via NewStringUTF, but the bytes stored in attrs_data come from String.getBytes(StandardCharsets.UTF_8) (standard UTF-8). NewStringUTF expects modified UTF-8, so values containing \u0000 or supplementary characters can be truncated/mis-decoded, making the test oracle incorrect.
    if (k == targetKey) {
      char buf[256];
      memcpy(buf, d + pos + 2, len);
      buf[len] = '\0';
      return env->NewStringUTF(buf);

ddprof-test-tracer/src/main/java/com/datadoghq/profiler/context/Tracing.java:86

  • Tracing.Context.close() only restores a parent context; when the stack becomes empty it leaves the last span context active in the profiler. With setTraceContext now rejecting spanId == 0, callers using this helper never clear the thread’s trace context, which can leak context into subsequent work on the same thread.
        private void notifyProfiler() {
            profiler.setTraceContext(rootSpanId, spanId, 0, spanId, -1, null, -1, null);
        }

rkennke added a commit to DataDog/dd-trace-java that referenced this pull request Jul 29, 2026
java-profiler's Phase 3 DBB-context removal (DataDog/java-profiler#696) deletes
ThreadContext, BufferWriter, BufferWriter8, and BufferWriter9. The GraalVM
native-image class-initialization config and reflection config here still
name them; a native-image build against the next ddprof release fails
resolving those classes. Drop the now-nonexistent entries ahead of the bump.
@dd-octo-sts

dd-octo-sts Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

CI Test Results

Run: #30627203505 | Commit: 519a457 | Duration: 18m 26s (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-07-31 11:50:14 UTC

vthread-context-cascade targeted a use-after-free specific to the removed
legacy DBB per-carrier-cached conduit; the all-native path resolves each
thread's context record fresh via ProfiledThread::current() on every call,
so that failure class no longer exists and there's no equivalent antagonist
to swap in. Drop the now-unknown name from run-chaos-harness.sh's
profiler+tracer default list so profiler+tracer chaos CI runs stop aborting
with "unknown antagonist".

ReapplyContextValueAntagonist.workerLoop also ignored setContextValue's
boolean return; fail fast on false so a dictionary-overflow or other
unexpected failure surfaces instead of silently losing coverage.
Copilot AI review requested due to automatic review settings July 29, 2026 11:44
run-threadcontext-benchmark.sh ran a JMH class (ThreadContextBenchmark)
that no longer exists; delete it.

Fix two javadoc references to methods deleted in the same change:
clearTraceContext()'s {@link #clearContext()} and
TraceContextAntagonist's description of the tracer's activation path,
now setTraceContext/clearTraceContext.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 50 out of 50 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/ReapplyContextValueAntagonist.java:73

  • ExecutorService.submit(...) captures any exception thrown by workerLoop() in the returned Future; since the future is ignored, a failure (e.g., IllegalStateException from checkSetContextValue) becomes silent and the chaos harness may keep running without surfacing the bug. Use execute(...) (or retain and inspect futures) so unexpected failures are visible/fail-fast.
    public void start() {
        running = true;
        for (int i = 0; i < workerCount; i++) {
            pool.submit(this::workerLoop);
        }

Copilot AI review requested due to automatic review settings July 29, 2026 11:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 50 out of 50 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

ddprof-lib/src/main/cpp/javaApi.cpp:1107

  • testReadContextAttribute0 builds a C string from the raw attrs_data bytes and returns it via NewStringUTF. The attribute value bytes are written as standard UTF-8 (from String.getBytes(UTF_8)), while NewStringUTF expects modified UTF-8 and will also truncate on embedded NULs. This makes the test oracle incorrect for non-ASCII values / U+0000 / supplementary characters.

Consider decoding the bytes to UTF-16 and using JNIEnv::NewString instead, so the read accessor round-trips the same UTF-8 that is stored in the record.

      char buf[256];
      memcpy(buf, d + pos + 2, len);
      buf[len] = '\0';
      return env->NewStringUTF(buf);
    }

Main's own javadoc documents the harness's only failure signal as a
non-zero process exit; an exception thrown on a background pool thread
doesn't produce one on its own, and submit()'s discarded Future would
have swallowed it entirely. Switch to execute() and halt the process on
failure so an unexpected setContextValue false actually fails the job,
per the intent of the original fail-fast fix.
Copilot AI review requested due to automatic review settings July 29, 2026 11:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 50 out of 50 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

utils/run-chaos-harness.sh:144

  • The new chaos antagonist reapply-context-value is documented (ddprof-stresstest/src/chaos/README.md) and wired in Main, but it isn't included in the script’s default antagonist sets. This means the intended replacement coverage won’t run in default profiler / profiler+tracer harness runs unless ANTAGONISTS_OVERRIDE is set.
    ddprof-lib/src/main/cpp/threadLocalData.h:95
  • This comment still refers to Java VarHandle views, but the DirectByteBuffer/VarHandle-based path was removed. The alignment note should be phrased in native terms to avoid confusion for future maintainers.
  // 8-byte aligned so VarHandle long views over this region require no unaligned access.

ddprof-lib/src/main/java/com/datadoghq/profiler/JavaProfiler.java:264

  • After removing the legacy setContext(...) API, call sites that don’t have activation attributes now need to pass the sentinel pair(s) -1, null to represent “no attributes”. Adding overloads for the 0-attr and 1-attr cases would make the API less error-prone and improve readability while keeping the combined native call as the implementation.
    public void setTraceContext(long rootSpanId, long spanId, long traceIdHigh, long traceIdLow,
                                int slot0, CharSequence v0, int slot1, CharSequence v1) {
        if (spanId == 0) {
            throw new IllegalArgumentException(
                    "spanId must be non-zero; use clearTraceContext() to clear the trace context");
        }
        requireActivationSlot(slot0);
        requireActivationSlot(slot1);
        ContextValueCache.Entry e0 = resolveContextValue(slot0, v0);
        ContextValueCache.Entry e1 = resolveContextValue(slot1, v1);
        setTraceContext0(rootSpanId, spanId, traceIdHigh, traceIdLow,
                e0 == null ? -1 : slot0, e0 == null ? 0 : e0.encoding, e0 == null ? null : e0.utf8,
                e1 == null ? -1 : slot1, e1 == null ? 0 : e1.encoding, e1 == null ? null : e1.utf8);
    }

@rkennke
rkennke marked this pull request as ready for review July 29, 2026 12:21
@dd-octo-sts

dd-octo-sts Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (commit e0b0e5b)

Pipeline: https://gitlab.ddbuild.io/DataDog/apm-reliability/benchmarking-platform/-/pipelines/127681331 Commit: e0b0e5bb41ce9ab2525a894bda594e4e4d326a77

⚠️ Significant outliers

  • 🔴 future-genetic (JDK 21): runtime +3.1% (2041→2105 ms)
Runtime details (per benchmark × JDK)
Benchmark JDK Latest Dev Δ (dev vs latest) Issues L/D
akka-uct 21 ✅ 10211 ms (21 iters) ✅ 10221 ms (21 iters) ≈ +0.1% (±11.1%) — / —
akka-uct 25 ✅ 8921 ms (24 iters) ✅ 8820 ms (24 iters) ≈ -1.1% (±10.3%) — / —
finagle-chirper 21 ✅ 6025 ms (33 iters) ✅ 6034 ms (33 iters) ≈ +0.1% (±24.6%) ⚠️ W:5 / ⚠️ W:3
finagle-chirper 25 ✅ 5467 ms (36 iters) ✅ 5478 ms (36 iters) ≈ +0.2% (±24.7%) ⚠️ W:3 / ⚠️ W:3
fj-kmeans 21 ✅ 2694 ms (70 iters) ✅ 2703 ms (69 iters) ≈ +0.3% (±2.7%) — / —
fj-kmeans 25 ✅ 2841 ms (66 iters) ✅ 2825 ms (66 iters) ≈ -0.6% (±2.5%) — / —
future-genetic 21 ✅ 2041 ms (90 iters) ✅ 2105 ms (89 iters) 🔴 +3.1% — / —
future-genetic 25 ✅ 1992 ms (93 iters) ✅ 1964 ms (95 iters) ≈ -1.4% (±2.5%) — / —
naive-bayes 21 ✅ 1260 ms (135 iters) ✅ 1245 ms (138 iters) ≈ -1.2% (±32.3%) — / —
naive-bayes 25 ✅ 1007 ms (170 iters) ✅ 983 ms (174 iters) ≈ -2.4% (±31.2%) — / —
reactors 21 ✅ 16599 ms (15 iters) ✅ 16640 ms (15 iters) ≈ +0.2% (±7.4%) — / —
reactors 25 ✅ 18698 ms (15 iters) ✅ 18409 ms (15 iters) ≈ -1.5% (±5%) — / —
Internal counter details (ddprof)

ddprof internal counters, latest / dev (✅ = 0, · = unavailable):

Benchmark JDK Dropped rec Dropped jvmti Dropped trace Skipped WC AGCT fail Unwind fail
akka-uct 21 ✅ / ✅ ✅ / ✅ 5 / 2 2024 / 1876 ✅ / ✅ ✅ / ✅
akka-uct 25 ✅ / ✅ ✅ / ✅ 3 / 1 2265 / 2304 ✅ / ✅ ✅ / ✅
finagle-chirper 21 ✅ / ✅ ✅ / ✅ 3 / 6 8571 / 8667 ✅ / ✅ ✅ / ✅
finagle-chirper 25 ✅ / ✅ ✅ / ✅ 1 / ✅ 8348 / 8527 ✅ / ✅ ✅ / ✅
fj-kmeans 21 ✅ / ✅ ✅ / ✅ 3 / ✅ 1311 / 1280 ✅ / ✅ ✅ / ✅
fj-kmeans 25 ✅ / ✅ ✅ / ✅ 1 / 1 1296 / 1281 ✅ / ✅ ✅ / ✅
future-genetic 21 ✅ / ✅ ✅ / ✅ 2 / 1 2956 / 2950 ✅ / ✅ ✅ / ✅
future-genetic 25 ✅ / ✅ ✅ / ✅ ✅ / ✅ 2952 / 2886 ✅ / ✅ ✅ / ✅
naive-bayes 21 ✅ / ✅ ✅ / ✅ 7 / 3 3504 / 3506 ✅ / ✅ ✅ / ✅
naive-bayes 25 ✅ / ✅ ✅ / ✅ 9 / 1 3483 / 3477 ✅ / ✅ ✅ / ✅
reactors 21 ✅ / ✅ ✅ / ✅ ✅ / ✅ 1614 / 1660 ✅ / ✅ ✅ / ✅
reactors 25 ✅ / ✅ ✅ / ✅ 2 / 1 1913 / 1800 ✅ / ✅ ✅ / ✅

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

ℹ️ 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".

@zhengyu123

Copy link
Copy Markdown
Contributor
  1. Stale/dead carrier-scoping build logic left behind (build-logic, not touched by this PR)
    build-logic/conventions/src/main/kotlin/com/datadoghq/profiler/ProfilerTestPlugin.kt still contains carrierExportJvmArgs() (and two call sites) which adds --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED on JDK 21+ test JVMs, plus ~20 lines of doc comments referencing OtelContextStorage.Mode.CARRIER and "carrier-scoping tests." That flag existed solely to resolve jdk.internal.misc.CarrierThreadLocal for OtelContextStorage's carrier-scoped mode — and the only tests that exercised it, CarrierContextStorageTest and OtelContextStorageModeTest, are deleted by this PR. A repo-wide grep confirms CarrierThreadLocal/jdk.internal.misc now appears only in this dead build-logic path, ContextCombinedBenchmark's JMH jvmArgsAppend (also now pointless — that benchmark's carrier/thread @Param and contextStorageMode() call were correctly removed, but the --add-exports annotation was left behind), and utils/run-chaos-harness.sh's --add-exports line. None of these are functionally broken (an unused --add-exports flag is harmless), but it directly contradicts the PR description's claim of a "grep sweep confirms no dangling references... outside history" — the sweep evidently didn't cover build-logic/ or these two leftover flag sites. Worth a follow-up cleanup pass.

  2. Test-coverage gap: custom context attributes → JFR field pipeline is no longer exercised end-to-end
    The deleted TagContextTest.test() was a substantial integration test: it drove ContextSetter/setContextAttribute, then verified (a) per-tag-value sample weight distribution in real datadog.MethodSample JFR events, (b) that jdk.ActiveSetting events correctly enumerate the configured contextattribute names, and (c) that the dictionary_context_keys JFR counter matches. The PR's replacement, ContextValueCacheTest, intentionally only ports the Dictionary-exhaustion/hash-collision unit coverage (as the PR description states), and AllNativeContextSamplingTest only verifies span/root-span propagation into JFR — not custom attribute values. I couldn't find any other test in the diff or existing suite that verifies a value written via the new setContextValue/ContextSetter.offsetOf path actually surfaces as a correctly-named, correctly-weighted JFR field. This is a real (if non-blocking) reduction in end-to-end coverage for a code path that customers actually consume (custom span tags in profiles) — worth either an explicit acknowledgment that it's covered elsewhere, or a follow-up test.

  3. reapply-context-value antagonist isn't wired into the default chaos harness run
    The new ReapplyContextValueAntagonist — introduced specifically to preserve UAF-risk stress coverage for the record this PR touches — is correctly registered in Main.java's factory and documented in the chaos README.md, but utils/run-chaos-harness.sh's DEFAULT_ANTAGONISTS list for the profiler+tracer config was not updated to include it (the old reapply-context wasn't in that list either, so this isn't a regression, but given the PR's stated purpose — proving the UAF class of bug is gone — it's a missed opportunity to make that proof run by default rather than only via ANTAGONISTS_OVERRIDE).

  4. Minor: ContextExecutor.beforeExecute rationale changed without full clarity on native semantics
    The old comment justified priming context via "avoid race condition with wall clock signals" against lazily-initialized TLS; the new comment reframes it as clearing stale context from thread-pool reuse. That reframing is accurate and the fix is sound — but note that clearTraceContext0 (unlike setTraceContext0) never calls ContextApi::initializeContextTLS, so it does not actually set isContextInitialized the way the old DBB-priming path did. I traced through ContextApi::get/wallClock.cpp's hasKnownActiveTraceContext and confirmed both gate on that flag and both correctly report "no context" either way (the record is zeroed regardless), so this isn't a functional bug — just worth double-checking against the original race this code was written to avoid, since the mechanism providing the guarantee changed even though the observable behavior didn't.

…t-value chaos antagonist, and close the custom-attribute JFR test gap

carrierExportJvmArgs()/testJvmMajorVersionFromRelease() and the two --add-exports
call sites in ProfilerTestPlugin.kt, ContextCombinedBenchmark's jvmArgsAppend, and
run-chaos-harness.sh's --add-exports line all existed solely to resolve
jdk.internal.misc.CarrierThreadLocal for OtelContextStorage's now-deleted
carrier-scoped mode; removed as dead weight.

Adds reapply-context-value to both DEFAULT_ANTAGONISTS lists so the chaos harness
exercises the antagonist that specifically targets the UAF class this PR removes,
by default rather than only via ANTAGONISTS_OVERRIDE.

Adds CustomContextAttributeSamplingTest, porting the weight-distribution/
jdk.ActiveSetting/dictionary_context_keys assertions from the deleted
TagContextTest onto the all-native setContextValue API, closing the coverage gap
between a value written through that API and it surfacing as a correctly-named,
correctly-weighted JFR field.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 30, 2026 18:07
@rkennke

rkennke commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough sweep — addressed in 0dfc51a:

  1. Dead carrier-scoping build logic: confirmed CarrierThreadLocal/jdk.internal.misc had no other referents. Removed carrierExportJvmArgs()/testJvmMajorVersionFromRelease() and both call sites from ProfilerTestPlugin.kt, the now-pointless jvmArgsAppend on ContextCombinedBenchmark, and the --add-exports line in run-chaos-harness.sh. Also generalized the stale doc comment in ConfigurationPresets that specifically called out carrier-scoping as its example.

  2. Test-coverage gap: added CustomContextAttributeSamplingTest, porting the weight-distribution / jdk.ActiveSetting / dictionary_context_keys assertions from the deleted TagContextTest.test() onto the all-native setContextValue API. Confirms a value written through setContextValue/ContextSetter surfaces as a correctly-named, correctly-weighted datadog.MethodSample field. Ran it (and the rest of the context package) locally — all green.

  3. reapply-context-value not defaulted: added it to both DEFAULT_ANTAGONISTS lists (it calls JavaProfiler directly, no tracer required, so it's not profiler+tracer-only like trace-context). It now runs by default rather than only via ANTAGONISTS_OVERRIDE.

  4. ContextExecutor semantics: traced through it — you're right that clearTraceContext0 never calls initializeContextTLS, unlike setTraceContext0/setContextValue0. But hasKnownActiveTraceContext (wallClock.cpp) doesn't gate on valid; it reads span_id directly after the isContextInitialized check, and clearTraceContext0 always zeroes span_id. So for a reused worker (already initialized from its previous task) the span_id==0 check correctly reports "no context", and for a never-initialized thread the isContextInitialized check does the same. Observable behavior is correct in both cases — no code change, just wanted to confirm the trace-through explicitly since you flagged the mechanism change.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 52 out of 52 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

ddprof-lib/src/main/cpp/javaApi.cpp:1106

  • testReadContextAttribute0 builds a C string and uses JNIEnv::NewStringUTF on raw attrs_data bytes. attrs_data stores standard UTF-8 from Java (including possible embedded NUL and 4-byte sequences for non-BMP characters), but NewStringUTF expects modified UTF-8 and a NUL-terminated string, so this can truncate or mis-decode values and make the test oracle incorrect.
      char buf[256];
      memcpy(buf, d + pos + 2, len);
      buf[len] = '\0';
      return env->NewStringUTF(buf);

build-logic/conventions/src/main/kotlin/com/datadoghq/profiler/ProfilerTestPlugin.kt:697

  • This comment mentions adding version-gated JVM flags in task doFirst blocks, but the plugin no longer adds any such flags. Updating this note avoids pointing readers at non-existent behavior and keeps the rationale (JAVA_TEST_HOME not resolvable at configuration time) accurate.
        // configuration time, where JAVA_TEST_HOME is not yet resolvable and
        // PlatformUtils.testJavaHome() falls back to the *build* JDK (JAVA_HOME) — which
        // misdetects in the musl split-JDK CI (build JDK 21, test JDK 8) and would emit a
        // JDK-21 flag onto a JDK-8 test JVM. Version-gated flags belong in the task doFirst
        // blocks instead (see ProfilerTestPlugin), where the real test JVM is resolvable.

ddprof-lib/src/main/java/com/datadoghq/profiler/ContextSetter.java:33

  • ContextSetter's constructor still takes a JavaProfiler instance but no longer uses it. Keeping an unused parameter makes the API misleading (it suggests the mapping depends on the profiler instance). If the parameter must remain for compatibility, renaming it to make the intent explicit helps prevent confusion.
    public ContextSetter(JavaProfiler profiler, List<String> attributes) {

Copilot AI review requested due to automatic review settings July 30, 2026 18:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 52 out of 52 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (3)

ddprof-lib/src/main/java/com/datadoghq/profiler/ContextSetter.java:40

  • ContextSetter claims to “deduplicate and truncate” to MAX_CONTEXT_SLOTS, but the loop truncates by input index before deduplication. If there are duplicates early in the list, the resulting attributes can end up with fewer than MAX_CONTEXT_SLOTS entries even when later unique attributes exist.
        for (int i = 0; i < Math.min(attributes.size(), JavaProfiler.MAX_CONTEXT_SLOTS); i++) {
            String attribute = attributes.get(i);
            if (unique.remove(attribute)) {
                this.attributes.add(attribute);
            }

ddprof-lib/src/main/java/com/datadoghq/profiler/JavaProfiler.java:286

  • Changing setContextValue from CharSequence to String is also a breaking API change; reintroducing the old signature as a delegating overload preserves compatibility while still keeping the String-optimized implementation.
    public boolean setContextValue(int slot, String value) {
        requireValidSlot(slot);
        ContextValueCache.Entry e = value == null ? null : contextValueCache.resolve(value);
        if (e == null) {

ddprof-lib/src/main/cpp/javaApi.cpp:1107

  • testReadContextAttribute0 builds a C string and uses NewStringUTF, but the stored bytes are standard UTF-8. This is incorrect for values containing \u0000 (encoded as 0x00 in UTF-8) because modified-UTF8 requires 0xC0 0x80; the current code will truncate at the first 0 byte.
      char buf[256];
      memcpy(buf, d + pos + 2, len);
      buf[len] = '\0';
      return env->NewStringUTF(buf);

Comment on lines 250 to 252
public void setTraceContext(long rootSpanId, long spanId, long traceIdHigh, long traceIdLow,
int slot0, CharSequence v0, int slot1, CharSequence v1) {
int slot0, String v0, int slot1, String v1) {
if (spanId == 0) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

All consumers are under our control. This is not important.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — reverted in f80a9b3. dd-trace-java's DatadogProfiler.setTraceContext forwards ProfilerContext#getOperationName()/getResourceName() directly into this method, and both are declared CharSequence throughout DDSpanContext's public span API (backed by allocation-free implementations like UTF8BytesString/SubSequence on the tracing hot path, not always java.lang.String). Narrowing to String would break that call site at compile time on the next ddprof-lib version bump.

setContextValue keeps its String param — dd-trace-java always passes an actual String there, so no compatibility concern on that one.

@dd-octo-sts

dd-octo-sts Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (commit 49ae4a3)

Pipeline: https://gitlab.ddbuild.io/DataDog/apm-reliability/benchmarking-platform/-/pipelines/128073339 Commit: 49ae4a33dd8cf6f706eab776314d81e7ca593ebd

⚠️ Significant outliers

  • 🟢 fj-kmeans (JDK 21): runtime -4.8% (2767→2633 ms)
Runtime details (per benchmark × JDK)
Benchmark JDK Latest Dev Δ (dev vs latest) Issues L/D
akka-uct 21 ✅ 10236 ms (21 iters) ✅ 10333 ms (21 iters) ≈ +0.9% (±11.5%) — / —
akka-uct 25 ✅ 8862 ms (24 iters) ✅ 8806 ms (24 iters) ≈ -0.6% (±10.1%) — / —
finagle-chirper 21 ✅ 5900 ms (33 iters) ✅ 5962 ms (33 iters) ≈ +1.1% (±25.2%) ⚠️ W:3 / ⚠️ W:3
finagle-chirper 25 ✅ 5485 ms (36 iters) ✅ 5432 ms (36 iters) ≈ -1% (±24.6%) ⚠️ W:3 / ⚠️ W:3
fj-kmeans 21 ✅ 2767 ms (68 iters) ✅ 2633 ms (72 iters) 🟢 -4.8% — / —
fj-kmeans 25 ✅ 2791 ms (67 iters) ✅ 2838 ms (66 iters) ≈ +1.7% (±2.7%) — / —
future-genetic 21 ✅ 2059 ms (90 iters) ✅ 2070 ms (90 iters) ≈ +0.5% (±2.5%) — / —
future-genetic 25 ✅ 2059 ms (90 iters) ✅ 2071 ms (90 iters) ≈ +0.6% (±2.7%) — / —
naive-bayes 21 ✅ 1235 ms (138 iters) ✅ 1256 ms (136 iters) ≈ +1.7% (±32.9%) — / —
naive-bayes 25 ✅ 1016 ms (168 iters) ✅ 970 ms (176 iters) ≈ -4.5% (±31.1%) — / —
reactors 21 ✅ 16585 ms (15 iters) ✅ 16464 ms (15 iters) ≈ -0.7% (±8%) — / —
reactors 25 ✅ 18534 ms (15 iters) ✅ 18444 ms (15 iters) ≈ -0.5% (±4.4%) — / —
Internal counter details (ddprof)

ddprof internal counters, latest / dev (✅ = 0, · = unavailable):

Benchmark JDK Dropped rec Dropped jvmti Dropped trace Skipped WC AGCT fail Unwind fail
akka-uct 21 ✅ / ✅ ✅ / ✅ 2 / 2 1899 / 1972 ✅ / ✅ ✅ / ✅
akka-uct 25 ✅ / ✅ ✅ / ✅ 4 / 3 2271 / 2200 ✅ / ✅ ✅ / ✅
finagle-chirper 21 ✅ / ✅ ✅ / ✅ 4 / 2 8513 / 8415 ✅ / ✅ ✅ / ✅
finagle-chirper 25 ✅ / ✅ ✅ / ✅ 1 / ✅ 8305 / 8283 ✅ / ✅ ✅ / ✅
fj-kmeans 21 ✅ / ✅ ✅ / ✅ 2 / 1 1272 / 1279 ✅ / ✅ ✅ / ✅
fj-kmeans 25 ✅ / ✅ ✅ / ✅ 1 / 3 1266 / 1300 ✅ / ✅ ✅ / ✅
future-genetic 21 ✅ / ✅ ✅ / ✅ 1 / 1 2987 / 2932 ✅ / ✅ ✅ / ✅
future-genetic 25 ✅ / ✅ ✅ / ✅ ✅ / 2 2911 / 2946 ✅ / ✅ ✅ / ✅
naive-bayes 21 ✅ / ✅ ✅ / ✅ 2 / 5 3501 / 3513 ✅ / ✅ ✅ / ✅
naive-bayes 25 ✅ / ✅ ✅ / ✅ 3 / 1 3455 / 3541 ✅ / ✅ ✅ / ✅
reactors 21 ✅ / ✅ ✅ / ✅ 2 / ✅ 1738 / 1636 ✅ / ✅ ✅ / ✅
reactors 25 ✅ / ✅ ✅ / ✅ ✅ / ✅ 1984 / 1883 ✅ / ✅ ✅ / ✅

@jbachorik jbachorik left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking good! Thanks for fixing all this!

…e the cache honor it

dd-trace-java's DatadogProfiler.setTraceContext forwards
ProfilerContext#getOperationName()/getResourceName() directly into this method,
both declared CharSequence throughout DDSpanContext's public span API —
UTF8BytesString and SubSequence exist specifically to avoid materializing a
String for these fields on the tracing hot path. Narrowing to String here would
break that call site at compile time on the next ddprof-lib version bump, and
runs counter to the tracer's own allocation-avoidance idiom. setContextValue
keeps its String param, since dd-trace-java always passes an actual String
there.

Since the whole point of accepting CharSequence is avoiding an eager String,
ContextValueCache gains a resolve(CharSequence) overload that never calls
toString() on a cache hit: contentHashCode() replicates String#hashCode()'s
documented polynomial algorithm (part of the API contract, not an
implementation detail) so a CharSequence and a content-equal cached String key
land in the same slot, and String#contentEquals(CharSequence) compares without
allocating. toString() is only paid on a genuine miss, where registerConstant0
needs a real String anyway.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 31, 2026 11:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 52 out of 52 changed files in this pull request and generated no new comments.

Suppressed comments (3)

ddprof-lib/src/main/cpp/javaApi.cpp:892

  • clearTraceContext0 does not call ContextApi::initializeContextTLS on a previously-uninitialized thread, unlike setTraceContext0/setContextValue0. This makes the all-native API inconsistent and prevents clearTraceContext() from being used as a safe “prime+clear” operation before wall-clock signals begin (it will leave isContextInitialized=false and otel_thread_ctx_v1 unpublished). Consider initializing TLS here as well.
  ProfiledThread* thrd = ProfiledThread::initCurrentThreadSignalSafe();
  if (thrd == nullptr) {
    return;
  }
  OtelThreadContextRecord* record = thrd->getOtelContextRecord();

ddprof-lib/src/main/cpp/threadLocalData.h:95

  • This comment still references VarHandle views, but the DirectByteBuffer/VarHandle-based writer path has been removed. Keeping this wording is misleading; consider updating it to describe the remaining alignment requirement for native/JNI/external readers instead.
  // 8-byte aligned so VarHandle long views over this region require no unaligned access.

ddprof-lib/src/main/java/com/datadoghq/profiler/ContextSetter.java:35

  • ContextSetter’s constructor still takes a JavaProfiler parameter but no longer uses it. If this is intentionally retained for compatibility with older callers, add a short in-code note so it’s clear the unused parameter is deliberate.
    public ContextSetter(JavaProfiler profiler, List<String> attributes) {
        Set<String> unique = new HashSet<>(attributes);
        this.attributes = new ArrayList<>(unique.size());

…he.resolve

resolve(String) and resolve(CharSequence) as separate overloads meant dispatch
depended on the caller's static type rather than the value's runtime type
(e.g. JavaProfiler.resolveContextValue's CharSequence-typed local always binds
to the CharSequence overload even when it happens to hold a String) — correct
today only because of the explicit instanceof check, but a footgun for future
callers who might assume Java picks the more specific runtime match. resolve
is now the single entrypoint; the String-only fast path moves to a private
resolveString helper.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 31, 2026 11:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 52 out of 52 changed files in this pull request and generated no new comments.

Suppressed comments (1)

ddprof-lib/src/main/cpp/javaApi.cpp:1106

  • testReadContextAttribute0 builds a C string and passes it to NewStringUTF, but attrs_data stores standard UTF-8 bytes (and can legally contain 0x00). NewStringUTF expects modified UTF-8 and treats 0x00 as terminator, so this test oracle can truncate or mis-decode values (and may fail on non-ASCII / supplementary chars). At minimum, guard against embedded NUL / non-ASCII so the helper fails predictably instead of returning an incorrect String.
      char buf[256];
      memcpy(buf, d + pos + 2, len);
      buf[len] = '\0';
      return env->NewStringUTF(buf);

@dd-octo-sts

dd-octo-sts Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (commit f80a9b3)

Pipeline: https://gitlab.ddbuild.io/DataDog/apm-reliability/benchmarking-platform/-/pipelines/128204501 Commit: f80a9b3876e005e354cec9b0db0be995101e4ae5

✅ Within expected boundaries

No significant runtime deltas (all within run-to-run noise) and no internal-counter outliers.

Runtime details (per benchmark × JDK)
Benchmark JDK Latest Dev Δ (dev vs latest) Issues L/D
akka-uct 21 ✅ 10359 ms (21 iters) ✅ 10424 ms (21 iters) ≈ +0.6% (±11.4%) — / —
akka-uct 25 ✅ 8873 ms (24 iters) ✅ 8794 ms (24 iters) ≈ -0.9% (±9.4%) — / —
finagle-chirper 21 ✅ 6000 ms (33 iters) ✅ 5935 ms (33 iters) ≈ -1.1% (±25.1%) ⚠️ W:3 / ⚠️ W:3
finagle-chirper 25 ✅ 5472 ms (36 iters) ✅ 5422 ms (36 iters) ≈ -0.9% (±24.2%) ⚠️ W:4 / ⚠️ W:3
fj-kmeans 21 ✅ 2724 ms (69 iters) ✅ 2683 ms (69 iters) ≈ -1.5% (±2.7%) — / —
fj-kmeans 25 ✅ 2811 ms (66 iters) ✅ 2808 ms (66 iters) ≈ -0.1% (±2.6%) — / —
future-genetic 21 ✅ 2123 ms (87 iters) ✅ 2097 ms (88 iters) ≈ -1.2% (±2.6%) — / —
future-genetic 25 ✅ 2100 ms (88 iters) ✅ 2047 ms (90 iters) ≈ -2.5% (±2.6%) — / —
naive-bayes 21 ✅ 1249 ms (137 iters) ✅ 1237 ms (137 iters) ≈ -1% (±32.1%) — / —
naive-bayes 25 ✅ 1009 ms (169 iters) ✅ 1013 ms (169 iters) ≈ +0.4% (±31.8%) — / —
reactors 21 ✅ 15986 ms (15 iters) ✅ 15989 ms (15 iters) ≈ +0% (±6.9%) — / —
reactors 25 ✅ 18271 ms (15 iters) ✅ 18709 ms (15 iters) ≈ +2.4% (±6.1%) — / —
Internal counter details (ddprof)

ddprof internal counters, latest / dev (✅ = 0, · = unavailable):

Benchmark JDK Dropped rec Dropped jvmti Dropped trace Skipped WC AGCT fail Unwind fail
akka-uct 21 ✅ / ✅ ✅ / ✅ 2 / 2 1976 / 1977 ✅ / ✅ ✅ / ✅
akka-uct 25 ✅ / ✅ ✅ / ✅ 1 / 1 1955 / 2388 ✅ / ✅ ✅ / ✅
finagle-chirper 21 ✅ / ✅ ✅ / ✅ ✅ / ✅ ✅ / ✅ ✅ / ✅ ✅ / ✅
finagle-chirper 25 ✅ / ✅ ✅ / ✅ ✅ / ✅ 8041 / 8349 ✅ / ✅ ✅ / ✅
fj-kmeans 21 ✅ / ✅ ✅ / ✅ ✅ / ✅ 1275 / 1253 ✅ / ✅ ✅ / ✅
fj-kmeans 25 ✅ / ✅ ✅ / ✅ 2 / 5 1266 / 1266 ✅ / ✅ ✅ / ✅
future-genetic 21 ✅ / ✅ ✅ / ✅ 4 / ✅ 3039 / 2967 ✅ / ✅ ✅ / ✅
future-genetic 25 ✅ / ✅ ✅ / ✅ ✅ / 1 2937 / 2953 ✅ / ✅ ✅ / ✅
naive-bayes 21 ✅ / ✅ ✅ / ✅ 4 / 8 3463 / 3499 ✅ / ✅ ✅ / ✅
naive-bayes 25 ✅ / ✅ ✅ / ✅ 1 / 1 3446 / 3479 ✅ / ✅ ✅ / ✅
reactors 21 ✅ / ✅ ✅ / ✅ 4 / ✅ 1607 / 1697 ✅ / ✅ ✅ / ✅
reactors 25 ✅ / ✅ ✅ / ✅ ✅ / 1 1815 / 1859 ✅ / ✅ ✅ / ✅

@rkennke
rkennke requested a review from jbachorik July 31, 2026 11:42
@dd-octo-sts

dd-octo-sts Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (commit 83c6d4c)

Pipeline: https://gitlab.ddbuild.io/DataDog/apm-reliability/benchmarking-platform/-/pipelines/128210036 Commit: 83c6d4ce89169c3197027d9dc4928c79e6a24197

⚠️ Significant outliers

  • 🟢 fj-kmeans (JDK 25): runtime -3.2% (2861→2769 ms)
Runtime details (per benchmark × JDK)
Benchmark JDK Latest Dev Δ (dev vs latest) Issues L/D
akka-uct 21 ✅ 10217 ms (21 iters) ✅ 10382 ms (21 iters) ≈ +1.6% (±11.2%) — / —
akka-uct 25 ✅ 8802 ms (24 iters) ✅ 8806 ms (24 iters) ≈ +0% (±9.6%) — / —
finagle-chirper 21 ✅ 5986 ms (33 iters) ✅ 5971 ms (33 iters) ≈ -0.3% (±25.9%) ⚠️ W:3 / ⚠️ W:3
finagle-chirper 25 ✅ 5510 ms (36 iters) ✅ 5401 ms (36 iters) ≈ -2% (±23.6%) ⚠️ W:3 / ⚠️ W:4
fj-kmeans 21 ✅ 2775 ms (67 iters) ✅ 2720 ms (68 iters) ≈ -2% (±2.7%) — / —
fj-kmeans 25 ✅ 2861 ms (66 iters) ✅ 2769 ms (68 iters) 🟢 -3.2% — / —
future-genetic 21 ✅ 2147 ms (87 iters) ✅ 2098 ms (88 iters) ≈ -2.3% (±2.7%) — / —
future-genetic 25 ✅ 2054 ms (90 iters) ✅ 2085 ms (89 iters) ≈ +1.5% (±2.8%) — / —
naive-bayes 21 ✅ 1254 ms (136 iters) ✅ 1279 ms (134 iters) ≈ +2% (±33.4%) — / —
naive-bayes 25 ✅ 1018 ms (167 iters) ✅ 1021 ms (168 iters) ≈ +0.3% (±31.9%) — / —
reactors 21 ✅ 16279 ms (15 iters) ✅ 15737 ms (15 iters) ≈ -3.3% (±7.5%) — / —
reactors 25 ✅ 18506 ms (15 iters) ✅ 18192 ms (15 iters) ≈ -1.7% (±5.2%) — / —
Internal counter details (ddprof)

ddprof internal counters, latest / dev (✅ = 0, · = unavailable):

Benchmark JDK Dropped rec Dropped jvmti Dropped trace Skipped WC AGCT fail Unwind fail
akka-uct 21 ✅ / ✅ ✅ / ✅ 4 / 2 1904 / 2031 ✅ / ✅ ✅ / ✅
akka-uct 25 ✅ / ✅ ✅ / ✅ 2 / ✅ 2250 / 2341 ✅ / ✅ ✅ / ✅
finagle-chirper 21 ✅ / ✅ ✅ / ✅ ✅ / 6 8585 / 8340 ✅ / ✅ ✅ / ✅
finagle-chirper 25 ✅ / ✅ ✅ / ✅ 2 / 2 8635 / 8258 ✅ / ✅ ✅ / ✅
fj-kmeans 21 ✅ / ✅ ✅ / ✅ 2 / 2 1238 / 1248 ✅ / ✅ ✅ / ✅
fj-kmeans 25 ✅ / ✅ ✅ / ✅ 3 / 6 1277 / 1279 ✅ / ✅ ✅ / ✅
future-genetic 21 ✅ / ✅ ✅ / ✅ ✅ / 3 3033 / 2970 ✅ / ✅ ✅ / ✅
future-genetic 25 ✅ / ✅ ✅ / ✅ 2 / ✅ 2881 / 3006 ✅ / ✅ ✅ / ✅
naive-bayes 21 ✅ / ✅ ✅ / ✅ 5 / 11 3485 / 3521 ✅ / ✅ ✅ / ✅
naive-bayes 25 ✅ / ✅ ✅ / ✅ 6 / 2 3466 / 3509 ✅ / ✅ ✅ / ✅
reactors 21 ✅ / ✅ ✅ / ✅ ✅ / ✅ 1625 / 1725 ✅ / ✅ ✅ / ✅
reactors 25 ✅ / ✅ ✅ / ✅ ✅ / ✅ 1887 / 1851 ✅ / ✅ ✅ / ✅

@rkennke rkennke removed the sphinx:critical Sphinx: critical — human review required label Jul 31, 2026
@rkennke
rkennke merged commit 22c3a7e into main Jul 31, 2026
113 checks passed
@rkennke
rkennke deleted the remove-legacy-dbb-context-storage branch July 31, 2026 18:08
@github-actions github-actions Bot added this to the 1.49.0 milestone Jul 31, 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.

4 participants