From 121d25ac3de6ba079274369dc549b07f5a5d7f31 Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Tue, 8 Sep 2026 16:07:04 -0400 Subject: [PATCH 1/2] QueryResult: add benchmark Signed-off-by: Jordan Liggitt --- api/prometheus/v1/api_bench_test.go | 126 ++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/api/prometheus/v1/api_bench_test.go b/api/prometheus/v1/api_bench_test.go index 5b434f72e..ed396243b 100644 --- a/api/prometheus/v1/api_bench_test.go +++ b/api/prometheus/v1/api_bench_test.go @@ -321,3 +321,129 @@ func BenchmarkRuleGroup(b *testing.B) { } }) } + +func BenchmarkQueryResult(b *testing.B) { + scalarData, err := json.Marshal(queryResult{ + Type: model.ValScalar, + Result: &model.Scalar{Value: 2, Timestamp: model.TimeFromUnix(1234)}, + }) + if err != nil { + b.Fatal(err) + } + + vectorData, err := json.Marshal(queryResult{ + Type: model.ValVector, + Result: model.Vector{genSample(), genSample(), genSample(), genSample(), genSample(), genSample(), genSample(), genSample(), genSample(), genSample()}, + }) + if err != nil { + b.Fatal(err) + } + + floatMatrix, histogramMatrix := generateData(10, 10) + floatData, err := json.Marshal(queryResult{ + Type: model.ValMatrix, + Result: floatMatrix, + }) + if err != nil { + b.Fatal(err) + } + + histogramData, err := json.Marshal(queryResult{ + Type: model.ValMatrix, + Result: histogramMatrix, + }) + if err != nil { + b.Fatal(err) + } + + b.Run("scalar", func(b *testing.B) { + for i := 0; i < b.N; i++ { + var q queryResult + if err := q.UnmarshalJSON(scalarData); err != nil { + b.Fatal(err) + } + } + }) + + b.Run("vector", func(b *testing.B) { + for i := 0; i < b.N; i++ { + var q queryResult + if err := q.UnmarshalJSON(vectorData); err != nil { + b.Fatal(err) + } + } + }) + + b.Run("matrix-float", func(b *testing.B) { + for i := 0; i < b.N; i++ { + var q queryResult + if err := q.UnmarshalJSON(floatData); err != nil { + b.Fatal(err) + } + } + }) + + b.Run("matrix-histogram", func(b *testing.B) { + for i := 0; i < b.N; i++ { + var q queryResult + if err := q.UnmarshalJSON(histogramData); err != nil { + b.Fatal(err) + } + } + }) +} + +func genSample() *model.Sample { + return &model.Sample{ + Metric: model.Metric{ + "name": "test_metric", + }, + Histogram: genSampleHistogram(), + Timestamp: 1234567, + } +} + +func genSampleHistogram() *model.SampleHistogram { + return &model.SampleHistogram{ + Count: 6, + Sum: 3897, + Buckets: model.HistogramBuckets{ + { + Boundaries: 1, + Lower: -4870.992343051145, + Upper: -4466.7196729968955, + Count: 1, + }, + { + Boundaries: 1, + Lower: -861.0779292198035, + Upper: -789.6119426088657, + Count: 1, + }, + { + Boundaries: 1, + Lower: -558.3399591246119, + Upper: -512, + Count: 1, + }, + { + Boundaries: 0, + Lower: 2048, + Upper: 2233.3598364984477, + Count: 1, + }, + { + Boundaries: 0, + Lower: 2896.3093757400984, + Upper: 3158.4477704354626, + Count: 1, + }, + { + Boundaries: 0, + Lower: 4466.7196729968955, + Upper: 4870.992343051145, + Count: 1, + }, + }, + } +} From 09eacad913abcfb3e4c72b69b7a19cd447cf55c8 Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Tue, 8 Sep 2026 16:12:08 -0400 Subject: [PATCH 2/2] QueryResult: use stdlib to decode envelope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit │ 1-query-main.txt │ 2-query-envelope.txt │ │ sec/op │ sec/op vs base │ QueryResult/scalar-14 473.4n ± 4% 731.7n ± 2% +54.58% (p=0.002 n=6) QueryResult/vector-14 74.66µ ± 9% 86.01µ ± 1% +15.20% (p=0.002 n=6) QueryResult/matrix-float-14 19.59µ ± 7% 26.84µ ± 2% +37.02% (p=0.002 n=6) QueryResult/matrix-histogram-14 168.8µ ± 3% 268.5µ ± 1% +59.11% (p=0.002 n=6) geomean 18.49µ 25.95µ +40.37% │ 1-query-main.txt │ 2-query-envelope.txt │ │ B/op │ B/op vs base │ QueryResult/scalar-14 544.0 ± 0% 704.0 ± 0% +29.41% (p=0.002 n=6) QueryResult/vector-14 38.04Ki ± 0% 37.88Ki ± 0% -0.43% (p=0.002 n=6) QueryResult/matrix-float-14 21.33Ki ± 0% 21.24Ki ± 0% -0.41% (p=0.002 n=6) QueryResult/matrix-histogram-14 133.2Ki ± 0% 131.5Ki ± 0% -1.23% (p=0.002 n=6) geomean 15.48Ki 16.42Ki +6.11% │ 1-query-main.txt │ 2-query-envelope.txt │ │ allocs/op │ allocs/op vs base │ QueryResult/scalar-14 16.00 ± 0% 17.00 ± 0% +6.25% (p=0.002 n=6) QueryResult/vector-14 747.0 ± 0% 689.0 ± 0% -7.76% (p=0.002 n=6) QueryResult/matrix-float-14 497.0 ± 0% 459.0 ± 0% -7.65% (p=0.002 n=6) QueryResult/matrix-histogram-14 4.567k ± 0% 4.229k ± 0% -7.40% (p=0.002 n=6) geomean 405.8 388.3 -4.32% Signed-off-by: Jordan Liggitt --- api/prometheus/v1/api.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/prometheus/v1/api.go b/api/prometheus/v1/api.go index d5e0980cf..2f9191a42 100644 --- a/api/prometheus/v1/api.go +++ b/api/prometheus/v1/api.go @@ -837,11 +837,11 @@ func (r *RecordingRule) unmarshalTypeCheckedJSON(b []byte) error { func (qr *queryResult) UnmarshalJSON(b []byte) error { v := struct { - Type model.ValueType `json:"resultType"` - Result json.RawMessage `json:"result"` + Type model.ValueType `json:"resultType"` + Result gojson.RawMessage `json:"result"` }{} - err := json.Unmarshal(b, &v) + err := gojson.Unmarshal(b, &v) if err != nil { return err } @@ -1184,7 +1184,7 @@ func (h *httpAPI) Query(ctx context.Context, query string, ts time.Time, opts .. } var qres queryResult - return qres.v, warnings, infos, json.Unmarshal(body, &qres) + return qres.v, warnings, infos, gojson.Unmarshal(body, &qres) } func (h *httpAPI) QueryRange(ctx context.Context, query string, r Range, opts ...Option) (model.Value, Warnings, Infos, error) {