Repository navigation
Conversation
…uce time Finding it scans the record's headers, which consumers did for every record even with time in queue off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
More details
Source review supports that skipping produce-time lookup when time in queue is disabled preserves span creation. The shared decoder preserves big-endian timestamp decoding and malformed-header fallback behavior.
🤖 Bits Code Review · Commit 2229ca6
🟢 Java Benchmark SLOs — All performance SLOs passed
PR vs. master results
Commit: Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion. |
Kafka / producer-benchmarkParameters
See matching parameters
SummaryFound 0 performance improvements and 1 performance regressions! Performance is the same for 2 metrics, 0 unstable metrics.
See unchanged results
|
Kafka / consumer-benchmarkParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 3 metrics, 0 unstable metrics. See unchanged results
|
What Does This Do
Kafka consumers (kafka-clients 0.11 and 3.8, and Kafka Streams) no longer look for a record's produce time when time in queue is off. Time in queue is off by default with legacy Kafka tracing. Before, every record scanned its headers for
x_datadog_kafka_produced, and the result was then thrown away.When time in queue is on, the produce time is read directly from the header's 8 bytes. Four copies of the
ByteBuffer.allocate(8)/put/flip/getLongcode become oneUtils.readProducedTimeinkafka-common. A value that isn't 8 bytes is still rejected, logged at debug and read as 0, as before.Motivation
This prepares for matching Kafka header keys as bytes (see below). On its own, the measured change is small.
KafkaConsumeScenariosBenchmark, which gains atimeInQueueparameter here, with 500-record batches throughTracingIterator(JDK 17, 3 forks, per record):dataStreamstimeInQueueThe time differences are within noise. The machine was not quiet (load 6–8), and the run after the change was the noisier one. With time in queue on, about 19 B per record of
ByteBuffergoes away; the DSM-on allocation difference is within the before run's error. The skipped scan is small here because the benchmark's headers haveStringkeys, and on 3.x clients extraction has already decoded and cached every key.Additional Notes
Next: matching Kafka header keys as bytes. Extraction will compare raw header key bytes against the keys our propagation styles, header tags, baggage and DSM read, and decode only the headers that match. In the Kafka consumer profile, decoding every header key and value cost about 370 B per record, and extraction was the largest tracer CPU bucket on the consumer thread.
Once extraction stops decoding keys, this produce-time scan, if it still ran first, would decode every key again on every record (
lastHeadercallskey()on each header). Checking the flag first removes that ahead of the change.Producer side is unchanged. It still writes the header with
ByteBuffer.allocate(8).putLong(...). A matchingwriteProducedTimecould follow separately.🤖 Generated with Claude Code