Files
Aliaksandr Valialkin 9fa9fc18a7 lib/protoparser/opentelemetry: eliminate memory allocations during parsing of samples send via OpenTelemetry protocol
This increases the parser performance by 4x-6x.

This commit uses the technique similar to https://github.com/VictoriaMetrics/VictoriaLogs/pull/720

goos: linux
goarch: amd64
pkg: github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/opentelemetry/stream
cpu: AMD Ryzen 7 PRO 5850U with Radeon Graphics
                                                    │   old.txt    │               new.txt               │
                                                    │    sec/op    │   sec/op     vs base                │
ParseStream/default-metrics-labels-formatting-16      15.565µ ± 1%   2.150µ ± 3%  -86.19% (p=0.000 n=10)
ParseStream/prometheus-metrics-labels-formatting-16   24.228µ ± 2%   4.355µ ± 1%  -82.02% (p=0.000 n=10)
ParseStream/prometheus-metrics-formatting-16          23.028µ ± 2%   3.395µ ± 1%  -85.26% (p=0.000 n=10)
geomean                                                20.55µ        3.168µ       -84.59%

                                                    │   old.txt    │                new.txt                 │
                                                    │     B/s      │      B/s       vs base                 │
ParseStream/default-metrics-labels-formatting-16      127.9Mi ± 1%    918.3Mi ± 3%  +617.82% (p=0.000 n=10)
ParseStream/prometheus-metrics-labels-formatting-16   82.19Mi ± 2%   453.32Mi ± 1%  +451.57% (p=0.000 n=10)
ParseStream/prometheus-metrics-formatting-16          86.47Mi ± 2%   581.56Mi ± 1%  +572.52% (p=0.000 n=10)
geomean                                               96.88Mi         623.3Mi       +543.34%

                                                    │   old.txt    │                 new.txt                  │
                                                    │     B/op     │    B/op      vs base                     │
ParseStream/default-metrics-labels-formatting-16      12.53Ki ± 0%   0.00Ki ± 0%  -100.00% (p=0.000 n=10)
ParseStream/prometheus-metrics-labels-formatting-16   21.15Ki ± 1%   0.00Ki ±  ?  -100.00% (p=0.000 n=10)
ParseStream/prometheus-metrics-formatting-16          20.74Ki ± 1%   0.00Ki ±  ?  -100.00% (p=0.000 n=10)
geomean                                               17.65Ki                     ?                       ¹ ²
¹ summaries must be >0 to compute geomean
² ratios must be >0 to compute geomean

                                                    │  old.txt   │                new.txt                 │
                                                    │ allocs/op  │ allocs/op  vs base                     │
ParseStream/default-metrics-labels-formatting-16      426.0 ± 0%    0.0 ± 0%  -100.00% (p=0.000 n=10)
ParseStream/prometheus-metrics-labels-formatting-16   514.0 ± 0%    0.0 ± 0%  -100.00% (p=0.000 n=10)
ParseStream/prometheus-metrics-formatting-16          514.0 ± 0%    0.0 ± 0%  -100.00% (p=0.000 n=10)
geomean                                               482.8                   ?                       ¹ ²
2025-12-10 16:11:59 +01:00

65 lines
1.5 KiB
Go

package pb
import (
"encoding/base64"
"strconv"
"github.com/valyala/fastjson"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
)
type fmtBuffer struct {
buf []byte
}
func (fb *fmtBuffer) reset() {
fb.buf = fb.buf[:0]
}
func (fb *fmtBuffer) formatInt(v int64) string {
n := len(fb.buf)
fb.buf = strconv.AppendInt(fb.buf, v, 10)
return bytesutil.ToUnsafeString(fb.buf[n:])
}
func (fb *fmtBuffer) formatFloat(v float64) string {
n := len(fb.buf)
fb.buf = strconv.AppendFloat(fb.buf, v, 'f', -1, 64)
return bytesutil.ToUnsafeString(fb.buf[n:])
}
func (fb *fmtBuffer) formatSubFieldName(prefix, suffix string) string {
if prefix == "" {
// There is no prefix, so just return the suffix as is.
return suffix
}
n := len(fb.buf)
fb.buf = append(fb.buf, prefix...)
fb.buf = append(fb.buf, '.')
fb.buf = append(fb.buf, suffix...)
return bytesutil.ToUnsafeString(fb.buf[n:])
}
func (fb *fmtBuffer) formatBase64(src []byte) string {
n := len(fb.buf)
fb.buf = base64.StdEncoding.AppendEncode(fb.buf, src)
return bytesutil.ToUnsafeString(fb.buf[n:])
}
func (fb *fmtBuffer) encodeJSONValue(v *fastjson.Value) string {
n := len(fb.buf)
fb.buf = v.MarshalTo(fb.buf)
return bytesutil.ToUnsafeString(fb.buf[n:])
}
func (fb *fmtBuffer) formatVmrange(start, end float64) string {
n := len(fb.buf)
fb.buf = strconv.AppendFloat(fb.buf, start, 'e', 3, 64)
fb.buf = append(fb.buf, "..."...)
fb.buf = strconv.AppendFloat(fb.buf, end, 'e', 3, 64)
return bytesutil.ToUnsafeString(fb.buf[n:])
}