Skip to content

fix(trace-utils): accept float32-encoded doubles in the v1 decoder - #2839

Merged
gyuheon0h merged 1 commit into
mainfrom
gyuheon0h/float32-encoded-doubles
Nov 9, 2026
Merged

gyuheon0h merged 1 commit into
mainfrom
gyuheon0h/float32-encoded-doubles

Conversation

@gyuheon0h

@gyuheon0h gyuheon0h commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Makes the v1 trace decoder accept a double attribute value (AnyValue type 3) encoded as msgpack float32 as well as float64. Integers and other markers are still rejected.

Motivation

dd-trace-c writes a double as float32 whenever float32 holds it exactly (1.0, 2.0, 43981.0, ...), saving 4 bytes per numeric attribute. It's valid msgpack, and the Agent's /v1.0/traces decoder accepts it. Our decoder rejected the whole payload with InvalidFormat("V1 attribute Double read failure"). Nearly every span has such an attribute (_dd.top_level = 1, _sampling_priority_v1 = 2), so in practice no dd-trace-c v1 payload could be decoded.

Additional Notes

The Agent's v1 decode path, from the HTTP handler down to the double read:

  1. /v1.0/traces is routed to handleTracesV1: pkg/trace/api/endpoints.go#L98-L99
  2. handleTracesV1 decodes the body with decodeConvertedTracerPayload: pkg/trace/api/api.go#L1174
  3. For V10, that calls idx.InternalTracerPayload.UnmarshalMsg: pkg/trace/api/api.go#L831-L838
  4. Span field 9 (attributes) is decoded by UnmarshalKeyValueMap: pkg/proto/pbgo/trace/idx/span.go#L127-L134
  5. That function reads each value with UnmarshalAnyValue: pkg/proto/pbgo/trace/idx/span.go#L296
  6. Value type 3 (double) is read with msgp.ReadFloat64Bytes: pkg/proto/pbgo/trace/idx/span.go#L386-L393
    case 3: // doubleValue
        var doubleValue float64
        doubleValue, o, err = msgp.ReadFloat64Bytes(o)
  7. The Agent pins github.com/tinylib/msgp v1.6.5:
    in that version, ReadFloat64Bytes widens a float32 and rejects any other marker:
  if b[0] != mfloat64 {
      if b[0] == mfloat32 {
          var tf float32
          tf, o, err = ReadFloat32Bytes(b)
          f = float64(tf)
          return
      }   
      err = badPrefix(Float64Type, b[0])
      return
  }   

Span-event attributes and array elements go through the same unmarshalAnyValue. Our decoder also routes all of these through read_typed_attribute_value, so the fix covers them too.

How to test the change?

Describe here in detail how the change can be validated.

@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

📚 Documentation Check Results

⚠️ 786 documentation warning(s) found

📦 libdd-trace-utils - 786 warning(s)


Updated: 2026-11-09 19:54:55 UTC | Commit: 0d5e6e6 | missing-docs job results

@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

🔒 Cargo Deny Results

⚠️ 5 issue(s) found, showing only errors (advisories, bans, sources)

📦 libdd-trace-utils - 5 error(s)

Show output
info: syncing channel updates for 1.91.1-x86_64-unknown-linux-gnu
info: latest update on 2025-11-10 for version 1.91.1 (ed61e7d7e 2025-11-07)
info: downloading 6 components
warn: the missing active toolchain `1.91.1-x86_64-unknown-linux-gnu` has been auto-installed
warn: this might cause rustup commands to take longer time to finish than expected
info: you may opt out with `RUSTUP_AUTO_INSTALL=0` or `rustup set auto-install disable`
error[vulnerability]: TLS 1.3 handshake messages incorrectly accepted across encryption level boundaries
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:217:1
    │
217 │ rustls 0.23.37 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0285
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0285
    ├ Rustls accepted TLS 1.3 handshake messages sent at the wrong encryption level
      when they followed a key-changing message in the same record. For example,
      a plaintext `EncryptedExtensions` message packed into the same record as the
      `ServerHello` was accepted.
      
      RFC 8446 section 5.1 requires that handshake messages do not span key changes,
      and that implementations terminate the connection with an "unexpected_message"
      alert if they do.
      
      The handshake transcript is still authenticated, so a network-position attacker
      cannot use this to alter or complete a handshake; the practical effect is that
      a peer could send handshake messages that should be encrypted in plaintext
      without rustls rejecting the connection.
      
      This is functionally the same bug as Go's
      [GO-2026-4340](https://pkg.go.dev/vuln/GO-2026-4340) (CVE-2025-61730).
    ├ Announcement: https://github.com/rustls/rustls/pull/3265
    ├ Solution: Upgrade to >=0.23.45 (try `cargo update -p rustls`)
    ├ rustls v0.23.37
      ├── hyper-rustls v0.27.7
      │   └── libdd-common v9.0.0
      │       ├── libdd-capabilities-impl v8.0.0
      │       │   └── libdd-trace-utils v15.0.0
      │       │       └── (dev) libdd-trace-utils v15.0.0 (*)
      │       └── libdd-trace-utils v15.0.0 (*)
      ├── libdd-common v9.0.0 (*)
      ├── rustls-platform-verifier v0.6.2
      │   └── libdd-common v9.0.0 (*)
      └── tokio-rustls v0.26.0
          ├── hyper-rustls v0.27.7 (*)
          └── (dev) libdd-common v9.0.0 (*)

error[vulnerability]: `Debug` impls for client session values expose TLS secrets
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:217:1
    │
217 │ rustls 0.23.37 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0346
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0346
    ├ The `Debug` implementations of `Tls12ClientSessionValue` and
      `Tls13ClientSessionValue` were derived, and so included the TLS 1.2 master
      secret or TLS 1.3 resumption PSK in their output.
      
      Custom `ClientSessionStore` implementations that format these values with
      `Debug` (for example, when logging) could disclose these secrets to readers of
      the logs. This conflicts with rustls's
      [key-material redaction policy](https://github.com/rustls/rustls/blob/99f2358cae2954837dbb866faf6727de75489ab9/SECURITY.md#boundary-public-api).
      
      Ordinary connection and built-in session cache `Debug` output is redacted and
      is not affected.
    ├ Announcement: https://github.com/rustls/rustls/pull/3299
    ├ Solution: Upgrade to >=0.23.46 (try `cargo update -p rustls`)
    ├ rustls v0.23.37
      ├── hyper-rustls v0.27.7
      │   └── libdd-common v9.0.0
      │       ├── libdd-capabilities-impl v8.0.0
      │       │   └── libdd-trace-utils v15.0.0
      │       │       └── (dev) libdd-trace-utils v15.0.0 (*)
      │       └── libdd-trace-utils v15.0.0 (*)
      ├── libdd-common v9.0.0 (*)
      ├── rustls-platform-verifier v0.6.2
      │   └── libdd-common v9.0.0 (*)
      └── tokio-rustls v0.26.0
          ├── hyper-rustls v0.27.7 (*)
          └── (dev) libdd-common v9.0.0 (*)

error[vulnerability]: Brotli certificate decompression can allocate up to 1 GiB before authentication
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:217:1
    │
217 │ rustls 0.23.37 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0348
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0348
    ├ The built-in Brotli certificate decompressor (enabled by the non-default
      `brotli` crate feature) bounded the size of the decompressed output, but
      accepted a peer-selected history window. Brotli's large-window extension was
      enabled, so a five-byte header could cause an allocation of 1 GiB. A peer can
      abort a process whose allocator cannot satisfy that request.
      
      No trusted certificate is required by the attacker. Affected configurations are:
      
      - clients that enable the `brotli` feature and connect to a malicious server, and
      - servers that enable the `brotli` feature and request client certificates.
      
      Applications that do not enable the `brotli` feature are not affected.
    ├ Announcement: https://github.com/rustls/rustls/pull/3297
    ├ Solution: Upgrade to >=0.23.46 (try `cargo update -p rustls`)
    ├ rustls v0.23.37
      ├── hyper-rustls v0.27.7
      │   └── libdd-common v9.0.0
      │       ├── libdd-capabilities-impl v8.0.0
      │       │   └── libdd-trace-utils v15.0.0
      │       │       └── (dev) libdd-trace-utils v15.0.0 (*)
      │       └── libdd-trace-utils v15.0.0 (*)
      ├── libdd-common v9.0.0 (*)
      ├── rustls-platform-verifier v0.6.2
      │   └── libdd-common v9.0.0 (*)
      └── tokio-rustls v0.26.0
          ├── hyper-rustls v0.27.7 (*)
          └── (dev) libdd-common v9.0.0 (*)

error[vulnerability]: Unauthenticated ServerHello can downgrade later connections to classical key exchange
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:217:1
    │
217 │ rustls 0.23.37 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0349
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0349
    ├ The client recorded the server-selected key exchange group for each server
      name when processing the ServerHello, before the server was authenticated.
      This record is used to predict which key share to send in future ClientHellos
      to that server name.
      
      A network attacker can answer one connection attempt with a ServerHello
      selecting X25519, and then close the connection. Later ClientHellos for that
      name carry only an X25519 key share, while `supported_groups` still lists
      X25519MLKEM768 first. If the genuine server accepts that share rather than
      sending a HelloRetryRequest for its preferred hybrid group, the handshake
      completes with classical-only key exchange and no error. This persists for as
      long as the entry stays in the client's session store.
      
      The impact is loss of post-quantum confidentiality for affected connections
      ("harvest now, decrypt later"). There is no key compromise and no
      authentication bypass.
      
      The following are not affected:
      
      - connections to servers which send a HelloRetryRequest for their preferred group,
      - clients with resumption disabled (as nothing is stored), and
      - other server names.
      
      This behaviour is discussed in
      [draft-ietf-tls-key-share-prediction](https://www.ietf.org/archive/id/draft-ietf-tls-key-share-prediction-01.html#name-security-considerations),
      so the practical impact depends largely on server policy.
    ├ Announcement: https://github.com/rustls/rustls/pull/3355
    ├ Solution: Upgrade to >=0.23.46 (try `cargo update -p rustls`)
    ├ rustls v0.23.37
      ├── hyper-rustls v0.27.7
      │   └── libdd-common v9.0.0
      │       ├── libdd-capabilities-impl v8.0.0
      │       │   └── libdd-trace-utils v15.0.0
      │       │       └── (dev) libdd-trace-utils v15.0.0 (*)
      │       └── libdd-trace-utils v15.0.0 (*)
      ├── libdd-common v9.0.0 (*)
      ├── rustls-platform-verifier v0.6.2
      │   └── libdd-common v9.0.0 (*)
      └── tokio-rustls v0.26.0
          ├── hyper-rustls v0.27.7 (*)
          └── (dev) libdd-common v9.0.0 (*)

error[unsound]: `AsyncFd::new` and related constructors violate I/O safety
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:268:1
    │
268 │ tokio 1.49.0 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unsound advisory detected
    │
    ├ ID: RUSTSEC-2026-0386
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0386
    ├ `tokio::io::unix::AsyncFd` provides safe constructors (`new`, `with_interest`, `try_new`, and `try_with_interest`) that accept any `T: AsRawFd` rather than requiring proof of ownership or validity of the file descriptor. Because `RawFd` implements `AsRawFd`, safe code can construct an `AsyncFd` from an arbitrary or closed file descriptor, or close/replace the underlying file descriptor while the `AsyncFd` is still alive.
      
      This violates I/O safety in two ways:
      
      1. `AsyncFd<T>` implements `AsFd` for all `T: AsRawFd` by calling `BorrowedFd::borrow_raw(self.as_raw_fd())`, allowing safe code to obtain an arbitrary `BorrowedFd<'_>` without owning the file descriptor.
      2. Tokio's I/O driver stores a pointer to an internal allocation in the `epoll`/`kqueue` user data for registered file descriptors. If the underlying file descriptor is duplicated and then closed while an `AsyncFd` is alive, and the OS reuses that file descriptor number for a another IO resource on the same runtime, dropping the first `AsyncFd` deregisters the reused file descriptor number and frees the first while the original file description remains registered in `epoll`, leading to a use-after-free when a readiness event fires.
      
      Starting in Tokio 1.51.6, 1.53.3, and 1.54.0, `AsyncFd::new`, `AsyncFd::with_interest`, `AsyncFd::try_new`, and `AsyncFd::try_with_interest` are deprecated in favor of the `unsafe` constructors `AsyncFd::register` and `AsyncFd::register_with_interest`. Callers must ensure that the file descriptor remains valid, open, and unchanged for the lifetime of the `AsyncFd`.
    ├ Announcement: https://github.com/tokio-rs/tokio/pull/8587
    ├ Solution: Upgrade to >=1.51.6, <1.52.0 OR >=1.53.3 (try `cargo update -p tokio`)
    ├ tokio v1.49.0
      ├── h2 v0.4.19
      │   └── hyper v1.11.1
      │       ├── httpmock v0.8.0-alpha.1
      │       │   └── libdd-trace-utils v15.0.0
      │       │       └── (dev) libdd-trace-utils v15.0.0 (*)
      │       ├── hyper-rustls v0.27.7
      │       │   └── libdd-common v9.0.0
      │       │       ├── libdd-capabilities-impl v8.0.0
      │       │       │   └── libdd-trace-utils v15.0.0 (*)
      │       │       └── libdd-trace-utils v15.0.0 (*)
      │       ├── hyper-util v0.1.17
      │       │   ├── httpmock v0.8.0-alpha.1 (*)
      │       │   ├── hyper-rustls v0.27.7 (*)
      │       │   └── libdd-common v9.0.0 (*)
      │       ├── libdd-common v9.0.0 (*)
      │       └── libdd-trace-utils v15.0.0 (*)
      ├── httpmock v0.8.0-alpha.1 (*)
      ├── hyper v1.11.1 (*)
      ├── hyper-rustls v0.27.7 (*)
      ├── hyper-util v0.1.17 (*)
      ├── (dev) libdd-capabilities-impl v8.0.0 (*)
      ├── (dev) libdd-common v9.0.0 (*)
      ├── (dev) libdd-trace-protobuf v5.1.1
      │   ├── libdd-trace-normalization v4.3.0
      │   │   └── libdd-trace-utils v15.0.0 (*)
      │   └── libdd-trace-utils v15.0.0 (*)
      ├── libdd-trace-utils v15.0.0 (*)
      ├── tokio-rustls v0.26.0
      │   ├── hyper-rustls v0.27.7 (*)
      │   └── (dev) libdd-common v9.0.0 (*)
      ├── tokio-util v0.7.12
      │   └── h2 v0.4.19 (*)
      └── (dev) tools v48.0.0
          ├── (dev) libdd-common v9.0.0 (*)
          └── (dev) libdd-trace-utils v15.0.0 (*)

advisories FAILED, bans ok, sources ok

Updated: 2026-11-09 19:56:38 UTC | Commit: 0d5e6e6 | dependency-check job results

@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Pipelines  Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
• Patch Coverage: 98.00%
• Overall Coverage: 87.14% (+3.45%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 8a857b5 | Docs | View more details | Give us feedback!

@gyuheon0h
gyuheon0h marked this pull request as ready for review November 9, 2026 20:10
@gyuheon0h
gyuheon0h requested a review from a team as a code owner November 9, 2026 20:10
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-09T20:11:45.893512Z 8a857b5 Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pr-commenter

pr-commenter Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

Benchmarks

Comparison

Benchmark execution time: 2026-11-09 20:11:39

Comparing candidate commit 8a857b5 in PR branch gyuheon0h/float32-encoded-doubles with baseline commit 5b156eb in branch main.

📊 Benchmarking dashboard

Found 10 performance improvements and 10 performance regressions! Performance is the same for 96 metrics, 10 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:vec_map/as_deduped_map/already_deduped/8

  • 🟩 execution_time [-1.973ns; -1.941ns] or [-13.630%; -13.407%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_10/128

  • 🟩 execution_time [-131.204ns; -128.186ns] or [-5.412%; -5.288%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_10/64

  • 🟩 execution_time [-58.744ns; -56.906ns] or [-4.650%; -4.505%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_10/8

  • 🟩 execution_time [-34.320ns; -34.073ns] or [-16.323%; -16.205%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_2/8

  • 🟩 execution_time [-37.089ns; -36.760ns] or [-14.344%; -14.217%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_4/128

  • 🟩 execution_time [-116.656ns; -114.275ns] or [-4.448%; -4.357%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_4/8

  • 🟩 execution_time [-35.735ns; -35.503ns] or [-15.941%; -15.837%]

scenario:vec_map/dedup/dup_1_in_10/8

  • 🟩 execution_time [-11.547ns; -9.684ns] or [-5.459%; -4.578%]

scenario:vec_map/dedup/no_duplicates/8

  • 🟩 execution_time [-26.998ns; -15.089ns] or [-14.136%; -7.901%]

scenario:vec_map/get_hit/128

  • 🟥 execution_time [+1.326µs; +1.340µs] or [+10.713%; +10.827%]
  • 🟥 throughput [-1011156.363op/s; -1000365.388op/s] or [-9.775%; -9.671%]

scenario:vec_map/get_hit/64

  • 🟥 execution_time [+304.468ns; +310.357ns] or [+9.051%; +9.226%]
  • 🟥 throughput [-1608060.748op/s; -1578179.724op/s] or [-8.452%; -8.295%]

scenario:vec_map/get_hit/8

  • 🟥 throughput [-8354696.908op/s; -5612337.631op/s] or [-6.439%; -4.325%]

scenario:vec_map/get_miss/8

  • 🟥 execution_time [+1.836ns; +1.875ns] or [+32.434%; +33.134%]

scenario:vec_map/get_mut/128

  • 🟥 execution_time [+1.616µs; +1.902µs] or [+11.432%; +13.450%]
  • 🟥 throughput [-1085866.554op/s; -940101.757op/s] or [-11.976%; -10.368%]

scenario:vec_map/get_mut/64

  • 🟥 execution_time [+391.979ns; +475.357ns] or [+10.062%; +12.203%]
  • 🟥 throughput [-1819501.923op/s; -1494185.631op/s] or [-11.057%; -9.080%]

scenario:vec_map/insert/8

  • 🟩 throughput [+1421258.149op/s; +1604977.789op/s] or [+4.083%; +4.611%]

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:span_pool/allocated_bytes/1x10/pooled

  • unstable execution_time [-1014.652ns; +456.854ns] or [-61.665%; +27.765%]
  • unstable throughput [-3936771.723op/s; +5297838.326op/s] or [-47.641%; +64.111%]

scenario:span_pool/allocated_bytes/20x100/pooled

  • unstable execution_time [-63.659µs; +190.379µs] or [-4.459%; +13.337%]
  • unstable throughput [-184890.430op/s; +50466.196op/s] or [-13.049%; +3.562%]

scenario:span_pool_v1/allocated_bytes/1x10/pooled

  • unstable execution_time [-377.065ns; +377.065ns] or [-20.595%; +20.595%]
  • unstable throughput [-1179919.915op/s; +1179919.915op/s] or [-20.555%; +20.555%]

scenario:span_pool_v1/allocated_bytes/20x100/pooled

  • unstable execution_time [-126975.308ns; +126975.308ns] or [-9.173%; +9.173%]
  • unstable throughput [-120187.026op/s; +120187.026op/s] or [-8.245%; +8.245%]

scenario:vec_map/get_mut/8

  • unstable execution_time [-1.133ns; +10.292ns] or [-1.274%; +11.568%]
  • unstable throughput [-11194801.879op/s; +949771.281op/s] or [-11.769%; +0.998%]
Benchmark execution time: 2026-11-09 20:07:29

Comparing candidate commit 8a857b5 in PR branch gyuheon0h/float32-encoded-doubles with baseline commit 5b156eb in branch main.

📊 Benchmarking dashboard

Found 3 performance improvements and 1 performance regressions! Performance is the same for 33 metrics, 24 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:glob_matcher/ascii_case_insensitive_match/wall_time

  • 🟩 execution_time [-10.786ns; -10.766ns] or [-27.614%; -27.561%]

scenario:glob_matcher/ascii_exact_match/wall_time

  • 🟩 execution_time [-10.835ns; -10.817ns] or [-27.742%; -27.698%]

scenario:glob_matcher/ascii_exact_miss/wall_time

  • 🟩 execution_time [-2.381ns; -2.345ns] or [-16.973%; -16.712%]

scenario:glob_matcher/ascii_pattern_unicode_subject/wall_time

  • 🟥 execution_time [+8.849ns; +8.982ns] or [+6.614%; +6.714%]

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:datadog_sample_span/complex_rule_matching/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+567.799%; -561.450%]

scenario:datadog_sample_span/complex_rule_partial_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+560.138%; -557.812%]

scenario:datadog_sample_span/many_attributes_tag_rule/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+551.925%; -553.945%]

scenario:datadog_sample_span/multiple_rules_first_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+550.881%; -553.456%]

scenario:datadog_sample_span/multiple_rules_last_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+562.504%; -558.933%]

scenario:datadog_sample_span/name_pattern_rule_matching/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+555.735%; -555.735%]

scenario:datadog_sample_span/name_pattern_rule_not_matching/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+555.735%; -555.735%]

scenario:datadog_sample_span/parent_not_sampled_short_circuit/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+557.026%; -556.343%]

scenario:datadog_sample_span/parent_sampled_short_circuit/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+556.471%; -556.081%]

scenario:datadog_sample_span/resource_pattern_rule_matching/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+555.735%; -555.735%]

scenario:datadog_sample_span/resource_pattern_rule_not_matching/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+552.876%; -554.391%]

scenario:datadog_sample_span/root_span_no_rules/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+553.727%; -554.791%]

scenario:datadog_sample_span/service_rule_matching/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+552.366%; -554.152%]

scenario:datadog_sample_span/service_rule_not_matching/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+551.246%; -553.627%]

scenario:datadog_sample_span/tag_rule_matching/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+555.735%; -555.735%]

scenario:datadog_sample_span/tag_rule_not_matching/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+550.932%; -553.480%]

scenario:glob_matcher/ascii_case_insensitive_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+457.500%; -512.726%]

scenario:glob_matcher/ascii_exact_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+457.412%; -512.691%]

scenario:glob_matcher/ascii_exact_miss/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+478.544%; -521.272%]

scenario:glob_matcher/ascii_wildcard_backtrack_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+554.107%; -554.969%]

scenario:glob_matcher/ascii_wildcard_heavy_backtrack/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+552.313%; -554.127%]

scenario:glob_matcher/ascii_wildcard_question_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+553.289%; -554.585%]

scenario:glob_matcher/ascii_wildcard_star_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+554.921%; -555.352%]

scenario:glob_matcher/star_short_circuit/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+554.395%; -555.104%]
Benchmark execution time: 2026-11-09 20:01:18

Comparing candidate commit 8a857b5 in PR branch gyuheon0h/float32-encoded-doubles with baseline commit 5b156eb in branch main.

📊 Benchmarking dashboard

Found 1 performance improvements and 22 performance regressions! Performance is the same for 34 metrics, 0 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:credit_card/is_card_number/ 3782-8224-6310-005

  • 🟥 execution_time [+5.264µs; +5.425µs] or [+7.057%; +7.272%]
  • 🟥 throughput [-909581.025op/s; -882821.888op/s] or [-6.785%; -6.585%]

scenario:credit_card/is_card_number/ 378282246310005

  • 🟥 execution_time [+5.455µs; +5.621µs] or [+8.030%; +8.275%]
  • 🟥 throughput [-1124576.017op/s; -1093156.796op/s] or [-7.640%; -7.426%]

scenario:credit_card/is_card_number/378282246310005

  • 🟥 execution_time [+5.693µs; +5.875µs] or [+8.853%; +9.137%]
  • 🟥 throughput [-1302349.983op/s; -1263341.305op/s] or [-8.374%; -8.124%]

scenario:credit_card/is_card_number/37828224631000521389798

  • 🟥 execution_time [+14.084µs; +14.118µs] or [+30.792%; +30.867%]
  • 🟥 throughput [-5159143.860op/s; -5145303.524op/s] or [-23.597%; -23.533%]

scenario:credit_card/is_card_number/x371413321323331

  • 🟥 execution_time [+1.238µs; +1.246µs] or [+18.863%; +18.991%]
  • 🟥 throughput [-24325431.147op/s; -24184212.839op/s] or [-15.960%; -15.867%]

scenario:credit_card/is_card_number_no_luhn/ 3782-8224-6310-005

  • 🟥 execution_time [+8.313µs; +8.597µs] or [+13.213%; +13.665%]
  • 🟥 throughput [-1923498.959op/s; -1850782.875op/s] or [-12.099%; -11.641%]

scenario:credit_card/is_card_number_no_luhn/ 378282246310005

  • 🟥 execution_time [+11.062µs; +11.112µs] or [+20.688%; +20.781%]
  • 🟥 throughput [-3218334.072op/s; -3205349.814op/s] or [-17.208%; -17.139%]

scenario:credit_card/is_card_number_no_luhn/378282246310005

  • 🟥 execution_time [+10.439µs; +10.489µs] or [+20.736%; +20.836%]
  • 🟥 throughput [-3428293.162op/s; -3409166.786op/s] or [-17.258%; -17.162%]

scenario:credit_card/is_card_number_no_luhn/37828224631000521389798

  • 🟥 execution_time [+14.067µs; +14.103µs] or [+30.748%; +30.825%]
  • 🟥 throughput [-5152472.277op/s; -5138132.271op/s] or [-23.573%; -23.507%]

scenario:credit_card/is_card_number_no_luhn/x371413321323331

  • 🟥 execution_time [+1.240µs; +1.248µs] or [+18.894%; +19.021%]
  • 🟥 throughput [-24359109.530op/s; -24213974.933op/s] or [-15.983%; -15.888%]

scenario:sql/obfuscate_sql_string

  • 🟩 execution_time [-18.719µs; -18.434µs] or [-6.774%; -6.670%]

scenario:trace_buffer/4_senders/no_delay

  • 🟥 execution_time [+104.898µs; +116.523µs] or [+5.568%; +6.185%]
  • 🟥 throughput [-111603.526op/s; -100496.504op/s] or [-5.840%; -5.259%]

Candidate

Omitted due to size.

Baseline

Omitted due to size.

@gyuheon0h
gyuheon0h merged commit 275cd7f into main Nov 9, 2026
97 of 100 checks passed
@gyuheon0h
gyuheon0h deleted the gyuheon0h/float32-encoded-doubles branch November 9, 2026 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants