Skip to content

Use stdlib to decode apiResult envelope - #2111

Merged
bwplotka merged 2 commits into
prometheus:mainfrom
liggitt:api-result
Sep 10, 2026
Merged

bwplotka merged 2 commits into
prometheus:mainfrom
liggitt:api-result

Conversation

@liggitt

@liggitt liggitt commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

cc @bwplotka

part of #2105

  1. Adds a benchmark for apiResult decoding
  2. Switches to stdlib for the envelope decoding

Benchmark results of switching the envelope decode to stdlib:

On Go 1.26:

  • CPU is about 180% slower than json-iter
  • Bytes range from ~flat (on larger complex responses) to ~2x json-iter
  • Allocs are consistently better, and way better than json-iter on large complex responses

On Go 1.27:

  • CPU is about 35% slower than json-iter
  • Bytes are improved 0-38% compared with json-iter
  • Allocs are improved 70-100% (!) over json-iter
goos: darwin
goarch: arm64
pkg: github.com/prometheus/client_golang/api/prometheus/v1
cpu: Apple M4 Pro
                                     │    main     │               go1.26.6               │              go1.27.1               │
                                     │   sec/op    │    sec/op     vs base                │    sec/op     vs base               │
APIResponse/AlertsResult-14            364.8n ± 1%   1054.0n ± 1%  +188.93% (p=0.002 n=6)   470.2n ±  1%  +28.88% (p=0.002 n=6)
APIResponse/AlertManagersResult-14     307.2n ± 1%    931.8n ± 1%  +203.34% (p=0.002 n=6)   408.9n ±  2%  +33.11% (p=0.002 n=6)
APIResponse/ConfigResult-14            191.0n ± 0%    577.6n ± 1%  +202.30% (p=0.002 n=6)   303.3n ±  2%  +58.75% (p=0.002 n=6)
APIResponse/FlagsResult-14             187.5n ± 1%    523.5n ± 0%  +179.13% (p=0.002 n=6)   297.6n ±  1%  +58.68% (p=0.002 n=6)
APIResponse/BuildinfoResult-14         311.1n ± 3%    904.2n ± 1%  +190.65% (p=0.002 n=6)   422.6n ±  2%  +35.84% (p=0.002 n=6)
APIResponse/RuntimeinfoResult-14       436.3n ± 2%   1258.0n ± 1%  +188.30% (p=0.002 n=6)   523.2n ±  1%  +19.90% (p=0.002 n=6)
APIResponse/model.LabelValues-14       189.3n ± 1%    546.9n ± 0%  +188.80% (p=0.002 n=6)   300.2n ±  1%  +58.54% (p=0.002 n=6)
APIResponse/SnapshotResult-14          191.6n ± 2%    535.3n ± 1%  +179.38% (p=0.002 n=6)   299.2n ±  1%  +56.18% (p=0.002 n=6)
APIResponse/TargetsResult-14           234.8n ± 1%    644.1n ± 1%  +174.32% (p=0.002 n=6)   331.9n ±  1%  +41.35% (p=0.002 n=6)
APIResponse/[]MetricMetadata-14        310.4n ± 1%    856.9n ± 0%  +176.05% (p=0.002 n=6)   422.1n ±  1%  +35.97% (p=0.002 n=6)
APIResponse/map[string][]Metadata-14   281.9n ± 1%    744.9n ± 1%  +164.29% (p=0.002 n=6)   379.6n ±  1%  +34.66% (p=0.002 n=6)
APIResponse/TSDBResult-14              676.0n ± 1%   1869.5n ± 1%  +176.55% (p=0.002 n=6)   792.2n ±  1%  +17.19% (p=0.002 n=6)
APIResponse/TSDBBlocksResult-14        518.7n ± 1%   1328.0n ± 0%  +156.02% (p=0.002 n=6)   597.2n ±  1%  +15.12% (p=0.002 n=6)
APIResponse/WalReplayStatus-14         247.3n ± 1%    615.8n ± 1%  +148.99% (p=0.002 n=6)   338.6n ± 14%  +36.92% (p=0.002 n=6)
APIResponse/[]ExemplarQueryResult-14   351.7n ± 1%    955.2n ± 1%  +171.65% (p=0.002 n=6)   450.0n ±  1%  +27.97% (p=0.002 n=6)
APIResponse/floats-10-14               3.875µ ± 2%   10.806µ ± 1%  +178.90% (p=0.002 n=6)   5.447µ ±  4%  +40.59% (p=0.002 n=6)
APIResponse/histograms-10-14           41.61µ ± 3%   143.34µ ± 0%  +244.52% (p=0.002 n=6)   49.72µ ±  1%  +19.50% (p=0.002 n=6)
APIResponse/floats-100-14              280.0µ ± 2%    790.3µ ± 1%  +182.22% (p=0.002 n=6)   423.2µ ±  2%  +51.14% (p=0.002 n=6)
APIResponse/histograms-100-14          4.000m ± 1%   14.083m ± 1%  +252.05% (p=0.002 n=6)   4.805m ±  2%  +20.12% (p=0.002 n=6)
APIResponse/floats-1000-14             27.73m ± 2%    77.84m ± 1%  +180.70% (p=0.002 n=6)   41.97m ±  3%  +51.34% (p=0.002 n=6)
APIResponse/histograms-1000-14         399.9m ± 2%   1424.6m ± 1%  +256.21% (p=0.002 n=6)   485.5m ±  4%  +21.39% (p=0.002 n=6)
geomean                                3.126µ         9.016µ       +188.41%                 4.238µ        +35.58%

                                     │     main     │               go1.26.6               │              go1.27.1               │
                                     │     B/op     │     B/op      vs base                │     B/op      vs base               │
APIResponse/AlertsResult-14              416.0 ± 0%     624.0 ± 0%   +50.00% (p=0.002 n=6)     288.0 ± 0%  -30.77% (p=0.002 n=6)
APIResponse/AlertManagersResult-14       360.0 ± 0%     512.0 ± 0%   +42.22% (p=0.002 n=6)     240.0 ± 0%  -33.33% (p=0.002 n=6)
APIResponse/ConfigResult-14              192.0 ± 0%     400.0 ± 0%  +108.33% (p=0.002 n=6)     160.0 ± 0%  -16.67% (p=0.002 n=6)
APIResponse/FlagsResult-14               192.0 ± 0%     384.0 ± 0%  +100.00% (p=0.002 n=6)     144.0 ± 0%  -25.00% (p=0.002 n=6)
APIResponse/BuildinfoResult-14           384.0 ± 0%     496.0 ± 0%   +29.17% (p=0.002 n=6)     256.0 ± 0%  -33.33% (p=0.002 n=6)
APIResponse/RuntimeinfoResult-14         536.0 ± 0%     592.0 ± 0%   +10.45% (p=0.002 n=6)     352.0 ± 0%  -34.33% (p=0.002 n=6)
APIResponse/model.LabelValues-14         192.0 ± 0%     392.0 ± 0%  +104.17% (p=0.002 n=6)     152.0 ± 0%  -20.83% (p=0.002 n=6)
APIResponse/SnapshotResult-14            192.0 ± 0%     384.0 ± 0%  +100.00% (p=0.002 n=6)     144.0 ± 0%  -25.00% (p=0.002 n=6)
APIResponse/TargetsResult-14             288.0 ± 0%     448.0 ± 0%   +55.56% (p=0.002 n=6)     176.0 ± 0%  -38.89% (p=0.002 n=6)
APIResponse/[]MetricMetadata-14          320.0 ± 0%     496.0 ± 0%   +55.00% (p=0.002 n=6)     224.0 ± 0%  -30.00% (p=0.002 n=6)
APIResponse/map[string][]Metadata-14     296.0 ± 0%     480.0 ± 0%   +62.16% (p=0.002 n=6)     208.0 ± 0%  -29.73% (p=0.002 n=6)
APIResponse/TSDBResult-14                784.0 ± 0%     752.0 ± 0%    -4.08% (p=0.002 n=6)     480.0 ± 0%  -38.78% (p=0.002 n=6)
APIResponse/TSDBBlocksResult-14          528.0 ± 0%     672.0 ± 0%   +27.27% (p=0.002 n=6)     336.0 ± 0%  -36.36% (p=0.002 n=6)
APIResponse/WalReplayStatus-14           272.0 ± 0%     416.0 ± 0%   +52.94% (p=0.002 n=6)     176.0 ± 0%  -35.29% (p=0.002 n=6)
APIResponse/[]ExemplarQueryResult-14     368.0 ± 0%     576.0 ± 0%   +56.52% (p=0.002 n=6)     240.0 ± 0%  -34.78% (p=0.002 n=6)
APIResponse/floats-10-14               3.500Ki ± 0%   3.453Ki ± 0%    -1.34% (p=0.002 n=6)   3.125Ki ± 0%  -10.71% (p=0.002 n=6)
APIResponse/histograms-10-14           42.06Ki ± 0%   40.45Ki ± 0%    -3.83% (p=0.002 n=6)   40.12Ki ± 0%   -4.61% (p=0.002 n=6)
APIResponse/floats-100-14              227.3Ki ± 0%   224.5Ki ± 0%    -1.26% (p=0.002 n=6)   224.1Ki ± 0%   -1.40% (p=0.002 n=6)
APIResponse/histograms-100-14          3.476Mi ± 0%   3.321Mi ± 0%    -4.47% (p=0.002 n=6)   3.320Mi ± 0%   -4.48% (p=0.002 n=6)
APIResponse/floats-1000-14             21.93Mi ± 0%   21.90Mi ± 0%    -0.14% (p=0.002 n=6)   21.90Mi ± 0%   -0.14% (p=0.002 n=6)
APIResponse/histograms-1000-14         353.1Mi ± 0%   337.9Mi ± 0%    -4.33% (p=0.002 n=6)   337.9Mi ± 0%   -4.33% (p=0.002 n=6)
geomean                                3.164Ki        4.257Ki        +34.51%                 2.394Ki       -24.36%

                                     │       main       │               go1.26.6                │              go1.27.1               │
                                     │    allocs/op     │  allocs/op   vs base                  │  allocs/op   vs base                │
APIResponse/AlertsResult-14                 16.000 ± 0%   10.000 ± 0%   -37.50% (p=0.002 n=6)     2.000 ±  0%   -87.50% (p=0.002 n=6)
APIResponse/AlertManagersResult-14          12.000 ± 0%    9.000 ± 0%   -25.00% (p=0.002 n=6)     2.000 ±  0%   -83.33% (p=0.002 n=6)
APIResponse/ConfigResult-14                  8.000 ± 0%    8.000 ± 0%         ~ (p=1.000 n=6) ¹   2.000 ±  0%   -75.00% (p=0.002 n=6)
APIResponse/FlagsResult-14                   8.000 ± 0%    8.000 ± 0%         ~ (p=1.000 n=6) ¹   2.000 ±  0%   -75.00% (p=0.002 n=6)
APIResponse/BuildinfoResult-14              14.000 ± 0%    8.000 ± 0%   -42.86% (p=0.002 n=6)     2.000 ±  0%   -85.71% (p=0.002 n=6)
APIResponse/RuntimeinfoResult-14            18.000 ± 0%    8.000 ± 0%   -55.56% (p=0.002 n=6)     2.000 ±  0%   -88.89% (p=0.002 n=6)
APIResponse/model.LabelValues-14             7.000 ± 0%    8.000 ± 0%   +14.29% (p=0.002 n=6)     2.000 ±  0%   -71.43% (p=0.002 n=6)
APIResponse/SnapshotResult-14                8.000 ± 0%    8.000 ± 0%         ~ (p=1.000 n=6) ¹   2.000 ±  0%   -75.00% (p=0.002 n=6)
APIResponse/TargetsResult-14                10.000 ± 0%    9.000 ± 0%   -10.00% (p=0.002 n=6)     2.000 ±  0%   -80.00% (p=0.002 n=6)
APIResponse/[]MetricMetadata-14             14.000 ± 0%    9.000 ± 0%   -35.71% (p=0.002 n=6)     2.000 ±  0%   -85.71% (p=0.002 n=6)
APIResponse/map[string][]Metadata-14        12.000 ± 0%    9.000 ± 0%   -25.00% (p=0.002 n=6)     2.000 ±  0%   -83.33% (p=0.002 n=6)
APIResponse/TSDBResult-14                   26.000 ± 0%    9.000 ± 0%   -65.38% (p=0.002 n=6)     2.000 ±  0%   -92.31% (p=0.002 n=6)
APIResponse/TSDBBlocksResult-14             22.000 ± 0%   10.000 ± 0%   -54.55% (p=0.002 n=6)     2.000 ±  0%   -90.91% (p=0.002 n=6)
APIResponse/WalReplayStatus-14              11.000 ± 0%    8.000 ± 0%   -27.27% (p=0.002 n=6)     2.000 ±  0%   -81.82% (p=0.002 n=6)
APIResponse/[]ExemplarQueryResult-14        15.000 ± 0%   10.000 ± 0%   -33.33% (p=0.002 n=6)     2.000 ±  0%   -86.67% (p=0.002 n=6)
APIResponse/floats-10-14                    48.000 ± 0%   10.000 ± 0%   -79.17% (p=0.002 n=6)     2.000 ±  0%   -95.83% (p=0.002 n=6)
APIResponse/histograms-10-14               348.000 ± 0%   10.000 ± 0%   -97.13% (p=0.002 n=6)     2.000 ±  0%   -99.43% (p=0.002 n=6)
APIResponse/floats-100-14                  408.000 ± 0%   10.000 ± 0%   -97.55% (p=0.002 n=6)     2.000 ±  0%   -99.51% (p=0.002 n=6)
APIResponse/histograms-100-14            30408.000 ± 0%   10.000 ± 0%   -99.97% (p=0.002 n=6)     2.000 ±  0%   -99.99% (p=0.002 n=6)
APIResponse/floats-1000-14                4008.000 ± 0%   10.000 ± 0%   -99.75% (p=0.002 n=6)     2.000 ±  0%   -99.95% (p=0.002 n=6)
APIResponse/histograms-1000-14         3004009.000 ± 0%   10.000 ± 0%  -100.00% (p=0.002 n=6)     4.000 ± 50%  -100.00% (p=0.002 n=6)
geomean                                      63.35         9.053        -85.71%                   2.067         -96.74%
¹ all samples are equal

@Karthik-Chowdary Karthik-Chowdary 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.

I reviewed the envelope-only decoder switch separately from the typed result decoding. Keeping Data as encoding/json.RawMessage preserves the raw payload for the existing second-stage decoders, so this does not broaden the behavior change into response models. The updated malformed-envelope expectation captures the one observable error-text change. The benchmark matrix also makes the tradeoff explicit: Go 1.26 pays CPU cost while allocations improve, and Go 1.27 substantially narrows that CPU gap. Given that this is scoped to the small response envelope and is part of the tracked jsoniter removal, the change looks sound.

@liggitt
liggitt force-pushed the api-result branch 2 times, most recently from 219ae94 to 4cc8635 Compare September 9, 2026 16:14

@bwplotka bwplotka left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks

Histograms are fun (alloc/op) (yet 3x slower)

APIResponse/histograms-1000-14 3004009.000 ± 0% 10.000 ± 0% -100.00% (p=0.002 n=6) 4.000 ± 50% -100.00% (p=0.002 n=6)

Signed-off-by: Jordan Liggitt <liggitt@google.com>
Signed-off-by: Jordan Liggitt <liggitt@google.com>
@liggitt

liggitt commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

rebased

@bwplotka
bwplotka merged commit 3f5d680 into prometheus:main Sep 10, 2026
15 checks passed
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.

3 participants