From: Maxim Merzhanov Date: Sun, 2 Nov 2025 11:28:31 +0000 (+0000) Subject: internal/profile: optimize Parse allocs X-Git-Tag: go1.26rc1~403 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c5559344acf76c6ddbbb6f222354a2dd88e0abba;p=gostls13.git internal/profile: optimize Parse allocs In our case, it greatly improves the performance of continuously collecting diff profiles from the net/http/pprof endpoint, such as /debug/pprof/allocs?seconds=30. This CL is a cherry-pick of my PR upstream: https://github.com/google/pprof/pull/951 Benchmark of profile Parse func: goos: linux goarch: amd64 pkg: github.com/google/pprof/profile cpu: 13th Gen Intel(R) Core(TM) i7-1360P │ old-parse.txt │ new-parse.txt │ │ sec/op │ sec/op vs base │ Parse-16 62.07m ± 13% 55.54m ± 13% -10.52% (p=0.035 n=10) │ old-parse.txt │ new-parse.txt │ │ B/op │ B/op vs base │ Parse-16 47.56Mi ± 0% 41.09Mi ± 0% -13.59% (p=0.000 n=10) │ old-parse.txt │ new-parse.txt │ │ allocs/op │ allocs/op vs base │ Parse-16 272.9k ± 0% 175.8k ± 0% -35.58% (p=0.000 n=10) Change-Id: I737ff9b9f815fdc56bc3b5743403717c4b6f07fd GitHub-Last-Rev: a09108f7ff7e6a27509f300d617e7adb36a9eb8a GitHub-Pull-Request: golang/go#76145 Reviewed-on: https://go-review.googlesource.com/c/go/+/717081 Reviewed-by: Michael Pratt Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI Reviewed-by: Florian Lehner --- diff --git a/src/internal/profile/proto.go b/src/internal/profile/proto.go index 58ff0ad2e0..ad6f621f88 100644 --- a/src/internal/profile/proto.go +++ b/src/internal/profile/proto.go @@ -24,6 +24,7 @@ package profile import ( "errors" "fmt" + "slices" ) type buffer struct { @@ -175,6 +176,16 @@ func le32(p []byte) uint32 { return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24 } +func peekNumVarints(data []byte) (numVarints int) { + for ; len(data) > 0; numVarints++ { + var err error + if _, data, err = decodeVarint(data); err != nil { + break + } + } + return numVarints +} + func decodeVarint(data []byte) (uint64, []byte, error) { var i int var u uint64 @@ -275,6 +286,9 @@ func decodeInt64(b *buffer, x *int64) error { func decodeInt64s(b *buffer, x *[]int64) error { if b.typ == 2 { // Packed encoding + dataLen := peekNumVarints(b.data) + *x = slices.Grow(*x, dataLen) + data := b.data for len(data) > 0 { var u uint64 @@ -305,8 +319,11 @@ func decodeUint64(b *buffer, x *uint64) error { func decodeUint64s(b *buffer, x *[]uint64) error { if b.typ == 2 { - data := b.data // Packed encoding + dataLen := peekNumVarints(b.data) + *x = slices.Grow(*x, dataLen) + + data := b.data for len(data) > 0 { var u uint64 var err error