Skip to content

WIP: optimize sample unmarshaling for json/v2 - #991

Open
liggitt wants to merge 7 commits into
prometheus:mainfrom
liggitt:json-v2-unmarshal
Open

liggitt wants to merge 7 commits into
prometheus:mainfrom
liggitt:json-v2-unmarshal

Conversation

@liggitt

@liggitt liggitt commented Sep 20, 2026

Copy link
Copy Markdown

Part of prometheus/client_golang#2105

  • Adds UnmarshalJSONFrom optimized streaming unmarshal implementations
  • Implementations are in build-tagged Go 1.27 files, previous version of Go still use less efficient unmarshalers
  • Adds a copy of the sample unmarshaling benchmark from client_golang
  • Adds unit tests to check parity between UnmarshalJSON and UnmarshalJSONFrom implementations
  • TMP: includes commits with benchmark output on go 1.26 and go 1.27 at each step, will drop those before merge

Go 1.27 performance is significantly improved:

benchstat 1-go1.27 3-go1.27 
goos: darwin
goarch: arm64
pkg: github.com/prometheus/common/model
cpu: Apple M4 Pro
                                                            │  1-go1.27   │              3-go1.27              │
                                                            │   sec/op    │   sec/op     vs base               │
SamplesJSONUnmarshal/series=10/dp=10/type=floats-14           56.57µ ± 2%   15.17µ ± 3%  -73.18% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=10/type=histograms-14       538.6µ ± 1%   252.9µ ± 1%  -53.04% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=floats-14          499.9µ ± 0%   106.1µ ± 4%  -78.78% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=histograms-14      5.379m ± 1%   2.491m ± 1%  -53.68% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=floats-14         5.015m ± 1%   1.029m ± 1%  -79.48% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=histograms-14     54.06m ± 1%   25.23m ± 1%  -53.32% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=floats-14          571.9µ ± 1%   148.8µ ± 1%  -73.98% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=histograms-14      5.478m ± 1%   2.547m ± 5%  -53.50% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=floats-14         5.132m ± 1%   1.127m ± 2%  -78.05% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=histograms-14     54.76m ± 1%   26.00m ± 3%  -52.53% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=floats-14        50.94m ± 1%   11.03m ± 2%  -78.34% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=histograms-14    551.0m ± 1%   267.8m ± 3%  -51.39% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=floats-14         5.744m ± 1%   1.604m ± 4%  -72.07% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=histograms-14     55.89m ± 1%   26.66m ± 4%  -52.30% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=floats-14        51.48m ± 1%   11.36m ± 2%  -77.94% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=histograms-14    557.5m ± 1%   266.1m ± 3%  -52.27% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=floats-14       511.5m ± 1%   112.4m ± 3%  -78.02% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=histograms-14    5.584 ± 1%    2.638 ± 1%  -52.75% (p=0.002 n=6)
geomean                                                       17.03m        5.638m       -66.89%

                                                            │   1-go1.27    │              3-go1.27               │
                                                            │     B/op      │     B/op      vs base               │
SamplesJSONUnmarshal/series=10/dp=10/type=floats-14           14.816Ki ± 0%   9.490Ki ± 0%  -35.95% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=10/type=histograms-14       122.76Ki ± 0%   44.67Ki ± 0%  -63.61% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=floats-14           92.10Ki ± 0%   44.52Ki ± 0%  -51.67% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=histograms-14      1175.4Ki ± 0%   400.1Ki ± 0%  -65.96% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=floats-14          967.2Ki ± 0%   497.2Ki ± 0%  -48.59% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=histograms-14     11.335Mi ± 0%   3.775Mi ± 0%  -66.70% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=floats-14          147.68Ki ± 0%   94.40Ki ± 0%  -36.08% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=histograms-14      1227.3Ki ± 0%   446.2Ki ± 0%  -63.64% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=floats-14          920.1Ki ± 0%   444.5Ki ± 0%  -51.69% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=histograms-14     11.471Mi ± 0%   3.905Mi ± 0%  -65.95% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=floats-14         9.438Mi ± 0%   4.853Mi ± 0%  -48.58% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=histograms-14    113.28Mi ± 0%   37.74Mi ± 0%  -66.69% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=floats-14         1471.7Ki ± 0%   939.6Ki ± 0%  -36.16% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=histograms-14     11.973Mi ± 0%   4.352Mi ± 0%  -63.65% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=floats-14         8.975Mi ± 0%   4.335Mi ± 0%  -51.69% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=histograms-14    114.63Mi ± 0%   39.04Mi ± 0%  -65.95% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=floats-14        94.37Mi ± 0%   48.53Mi ± 0%  -48.58% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=histograms-14   1132.7Mi ± 0%   377.3Mi ± 0%  -66.69% (p=0.002 n=6)
geomean                                                        3.521Mi        1.523Mi       -56.74%

                                                            │   1-go1.27    │              3-go1.27              │
                                                            │   allocs/op   │  allocs/op   vs base               │
SamplesJSONUnmarshal/series=10/dp=10/type=floats-14              426.0 ± 0%    116.0 ± 0%  -72.77% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=10/type=histograms-14         5.226k ± 0%   1.216k ± 0%  -76.73% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=floats-14            3156.0 ± 0%    146.0 ± 0%  -95.37% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=histograms-14        51.16k ± 0%   11.15k ± 0%  -78.21% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=floats-14          30197.0 ± 0%    186.0 ± 0%  -99.38% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=histograms-14       510.2k ± 0%   110.2k ± 0%  -78.41% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=floats-14            4.209k ± 0%   1.109k ± 0%  -73.65% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=histograms-14        52.21k ± 0%   12.11k ± 0%  -76.81% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=floats-14          31.510k ± 0%   1.409k ± 0%  -95.53% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=histograms-14       511.5k ± 0%   111.4k ± 0%  -78.22% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=floats-14        301.911k ± 0%   1.809k ± 0%  -99.40% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=histograms-14      5.102M ± 0%   1.102M ± 0%  -78.41% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=floats-14           42.03k ± 0%   11.03k ± 0%  -73.76% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=histograms-14       522.1k ± 0%   121.0k ± 0%  -76.82% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=floats-14         315.03k ± 0%   14.03k ± 0%  -95.55% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=histograms-14      5.115M ± 0%   1.114M ± 0%  -78.22% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=floats-14       3019.04k ± 0%   18.03k ± 0%  -99.40% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=histograms-14     51.02M ± 0%   11.02M ± 0%  -78.41% (p=0.002 n=6)
geomean                                                         132.8k        12.77k       -90.38%

Go 1.26 CPU performance is slightly improved by dropping an unnecessary custom UnmarshalJSON method:

benchstat 1-go1.26 3-go1.26 
goos: darwin
goarch: arm64
pkg: github.com/prometheus/common/model
cpu: Apple M4 Pro
                                                            │   1-go1.26   │              3-go1.26              │
                                                            │    sec/op    │   sec/op     vs base               │
SamplesJSONUnmarshal/series=10/dp=10/type=floats-14           59.13µ ±  3%   44.60µ ± 3%  -24.58% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=10/type=histograms-14       760.4µ ±  1%   586.7µ ± 0%  -22.84% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=floats-14          476.0µ ±  4%   382.1µ ± 1%  -19.73% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=histograms-14      7.449m ±  1%   5.880m ± 1%  -21.07% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=floats-14         4.698m ±  1%   3.799m ± 2%  -19.13% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=histograms-14     76.79m ±  3%   59.98m ± 1%  -21.89% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=floats-14          586.1µ ±  2%   451.7µ ± 1%  -22.94% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=histograms-14      7.550m ±  1%   5.947m ± 0%  -21.22% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=floats-14         4.714m ±  0%   3.855m ± 2%  -18.22% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=histograms-14     75.83m ±  1%   59.81m ± 0%  -21.14% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=floats-14        47.63m ±  3%   38.68m ± 3%  -18.80% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=histograms-14    839.1m ± 43%   617.9m ± 0%  -26.36% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=floats-14         6.479m ± 11%   4.566m ± 1%  -29.53% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=histograms-14     81.97m ±  2%   60.11m ± 1%  -26.67% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=floats-14        51.16m ±  2%   39.35m ± 1%  -23.10% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=histograms-14    804.5m ±  1%   619.6m ± 1%  -22.98% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=floats-14       478.6m ±  2%   394.4m ± 1%  -17.59% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=histograms-14    7.861 ±  2%    6.218 ± 1%  -20.89% (p=0.002 n=6)
geomean                                                       20.15m         15.67m       -22.21%

                                                            │   1-go1.26   │              3-go1.26               │
                                                            │     B/op     │     B/op      vs base               │
SamplesJSONUnmarshal/series=10/dp=10/type=floats-14           31.16Ki ± 0%   28.02Ki ± 0%  -10.08% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=10/type=histograms-14       220.9Ki ± 0%   217.1Ki ± 0%   -1.71% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=floats-14          227.9Ki ± 0%   224.7Ki ± 0%   -1.38% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=histograms-14      2.073Mi ± 0%   2.070Mi ± 0%   -0.18% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=floats-14         2.244Mi ± 0%   2.241Mi ± 0%   -0.14% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=histograms-14     20.56Mi ± 0%   20.56Mi ± 0%   -0.02% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=floats-14          309.4Ki ± 0%   277.4Ki ± 0%  -10.33% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=histograms-14      2.155Mi ± 0%   2.117Mi ± 0%   -1.73% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=floats-14         2.223Mi ± 0%   2.192Mi ± 0%   -1.40% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=histograms-14     20.73Mi ± 0%   20.69Mi ± 0%   -0.18% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=floats-14        22.43Mi ± 0%   22.40Mi ± 0%   -0.14% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=histograms-14    205.6Mi ± 0%   205.6Mi ± 0%   -0.02% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=floats-14         3.015Mi ± 0%   2.703Mi ± 0%  -10.37% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=histograms-14     21.54Mi ± 0%   21.17Mi ± 0%   -1.74% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=floats-14        22.23Mi ± 0%   21.91Mi ± 0%   -1.41% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=histograms-14    207.3Mi ± 0%   206.9Mi ± 0%   -0.18% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=floats-14       224.3Mi ± 0%   224.0Mi ± 0%   -0.14% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=histograms-14   2.008Gi ± 0%   2.008Gi ± 0%   -0.02% (p=0.002 n=6)
geomean                                                       7.195Mi        7.025Mi        -2.36%

                                                            │  1-go1.26   │              3-go1.26              │
                                                            │  allocs/op  │  allocs/op   vs base               │
SamplesJSONUnmarshal/series=10/dp=10/type=floats-14            530.0 ± 0%    462.0 ± 0%  -12.83% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=10/type=histograms-14       4.541k ± 0%   4.463k ± 0%   -1.72% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=floats-14          3.260k ± 0%   3.192k ± 0%   -2.09% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=100/type=histograms-14      43.27k ± 0%   43.19k ± 0%   -0.18% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=floats-14         30.30k ± 0%   30.23k ± 0%   -0.22% (p=0.002 n=6)
SamplesJSONUnmarshal/series=10/dp=1000/type=histograms-14     430.3k ± 0%   430.2k ± 0%   -0.02% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=floats-14          5.213k ± 0%   4.515k ± 0%  -13.39% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=10/type=histograms-14      45.31k ± 0%   44.52k ± 0%   -1.76% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=floats-14         32.51k ± 0%   31.82k ± 0%   -2.15% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=100/type=histograms-14     432.6k ± 0%   431.8k ± 0%   -0.18% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=floats-14        302.9k ± 0%   302.2k ± 0%   -0.23% (p=0.002 n=6)
SamplesJSONUnmarshal/series=100/dp=1000/type=histograms-14    4.303M ± 0%   4.302M ± 0%   -0.02% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=floats-14         52.02k ± 0%   45.02k ± 0%  -13.45% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=10/type=histograms-14     453.0k ± 0%   445.0k ± 0%   -1.77% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=floats-14        325.0k ± 0%   318.0k ± 0%   -2.15% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=100/type=histograms-14    4.326M ± 0%   4.318M ± 0%   -0.18% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=floats-14       3.029M ± 0%   3.022M ± 0%   -0.23% (p=0.002 n=6)
SamplesJSONUnmarshal/series=1000/dp=1000/type=histograms-14   43.03M ± 0%   43.02M ± 0%   -0.02% (p=0.002 n=6)
geomean                                                       127.8k        123.9k        -3.04%

cc @bwplotka

Signed-off-by: Jordan Liggitt <liggitt@google.com>
Signed-off-by: Jordan Liggitt <liggitt@google.com>
5-20% CPU improvement
0-12% alloc/memory improvement

Signed-off-by: Jordan Liggitt <liggitt@google.com>
Signed-off-by: Jordan Liggitt <liggitt@google.com>
Signed-off-by: Jordan Liggitt <liggitt@google.com>
Signed-off-by: Jordan Liggitt <liggitt@google.com>
Signed-off-by: Jordan Liggitt <liggitt@google.com>
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.

1 participant