Skip to content

Commit 8b0e81b

Browse files
authored
Merge pull request #8547 from thanos-io/pull_fix
Pull extgrpc fix and release 0.40.1
2 parents 52542b9 + 010fbd5 commit 8b0e81b

File tree

4 files changed

+142
-4
lines changed

4 files changed

+142
-4
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan
88

99
We use *breaking :warning:* to mark changes that are not backward compatible (relates only to v0.y.z releases.)
1010

11+
## [v0.40.1](https://github.com/thanos-io/thanos/tree/release-0.40) - 2025 10 28
12+
13+
### Fixed
14+
15+
- [#8545](https://github.com/thanos-io/thanos/pull/8545) extgrpc: call gogo methods from the codec
16+
17+
### Added
18+
19+
### Changed
20+
1121
## [v0.40.0](https://github.com/thanos-io/thanos/tree/release-0.40) - 2025 10 27
1222

1323
### Fixed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.40.0
1+
0.40.1

pkg/extgrpc/client.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ type nonPoolingCodec struct {
3232
}
3333

3434
func init() {
35-
encoding.RegisterCodecV2(&nonPoolingCodec{CodecV2: encoding.GetCodecV2("proto")})
35+
encoding.RegisterCodecV2(&nonPoolingCodec{
36+
CodecV2: encoding.GetCodecV2("proto"),
37+
})
38+
}
39+
40+
func (n *nonPoolingCodec) Name() string {
41+
return "proto"
3642
}
3743

3844
func messageV2Of(v any) protobufproto.Message {
@@ -57,8 +63,29 @@ func (n *nonPoolingCodec) Unmarshal(data mem.BufferSlice, v any) error {
5763
return nil
5864
}
5965

60-
func (n *nonPoolingCodec) Marshal(v any) (out mem.BufferSlice, err error) {
61-
return n.CodecV2.Marshal(v)
66+
type gogoMsg interface {
67+
Size() int
68+
MarshalToSizedBuffer([]byte) (int, error)
69+
}
70+
71+
func (c *nonPoolingCodec) Marshal(v any) (mem.BufferSlice, error) {
72+
gmsg, ok := v.(gogoMsg)
73+
if !ok {
74+
return c.CodecV2.Marshal(v)
75+
}
76+
size := gmsg.Size()
77+
pool := mem.DefaultBufferPool()
78+
buf := pool.Get(size)
79+
80+
n, err := gmsg.MarshalToSizedBuffer((*buf)[:size])
81+
if err != nil {
82+
pool.Put(buf)
83+
return mem.BufferSlice{}, err
84+
}
85+
86+
bufExact := (*buf)[:n]
87+
88+
return mem.BufferSlice{mem.NewBuffer(&bufExact, pool)}, nil
6289
}
6390

6491
// EndpointGroupGRPCOpts creates gRPC dial options for connecting to endpoint groups.

pkg/extgrpc/client_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright (c) The Thanos Authors.
2+
// Licensed under the Apache License 2.0.
3+
4+
package extgrpc
5+
6+
import (
7+
"testing"
8+
9+
"github.com/prometheus/prometheus/model/labels"
10+
"github.com/stretchr/testify/require"
11+
"github.com/thanos-io/thanos/pkg/info/infopb"
12+
"github.com/thanos-io/thanos/pkg/store/labelpb"
13+
"google.golang.org/grpc/encoding"
14+
)
15+
16+
func BenchmarkVanillaProtoMarshal(b *testing.B) {
17+
ls := []labels.Labels{}
18+
19+
for i := range 1000 {
20+
ls = append(ls, labels.FromStrings("label_"+string(rune(i)), "value_"+string(rune(i))))
21+
}
22+
i := &infopb.InfoResponse{
23+
LabelSets: labelpb.ZLabelSetsFromPromLabels(
24+
ls...,
25+
),
26+
ComponentType: "asdsadsadsa",
27+
Store: &infopb.StoreInfo{
28+
MinTime: 123,
29+
MaxTime: 456,
30+
SupportsSharding: true,
31+
TsdbInfos: []infopb.TSDBInfo{
32+
{
33+
Labels: labelpb.ZLabelSet{Labels: labelpb.ZLabelsFromPromLabels(labels.FromStrings("replica", "1"))},
34+
MinTime: 100,
35+
MaxTime: 200,
36+
},
37+
},
38+
},
39+
Rules: &infopb.RulesInfo{},
40+
MetricMetadata: &infopb.MetricMetadataInfo{},
41+
Exemplars: &infopb.ExemplarsInfo{
42+
MinTime: 100,
43+
MaxTime: 200,
44+
},
45+
}
46+
47+
c := &nonPoolingCodec{}
48+
49+
ogCodec := encoding.GetCodecV2("proto").(*nonPoolingCodec).CodecV2
50+
51+
b.Run("vanilla proto marshal", func(b *testing.B) {
52+
b.ReportAllocs()
53+
b.ResetTimer()
54+
55+
for b.Loop() {
56+
_, err := ogCodec.Marshal(i)
57+
require.NoError(b, err)
58+
}
59+
})
60+
61+
b.Run("non pooling codec marshal", func(b *testing.B) {
62+
for b.Loop() {
63+
_, err := c.Marshal(i)
64+
require.NoError(b, err)
65+
}
66+
})
67+
}
68+
69+
func TestNonPoolingCodecMarshal(t *testing.T) {
70+
i := &infopb.InfoResponse{
71+
LabelSets: labelpb.ZLabelSetsFromPromLabels(
72+
labels.FromStrings("foo", "bar"),
73+
labels.FromStrings("baz", "qux"),
74+
labels.FromStrings("aaa", "bbb"),
75+
),
76+
ComponentType: "asdsadsadsa",
77+
Store: &infopb.StoreInfo{
78+
MinTime: 123,
79+
MaxTime: 456,
80+
SupportsSharding: true,
81+
TsdbInfos: []infopb.TSDBInfo{
82+
{
83+
Labels: labelpb.ZLabelSet{Labels: labelpb.ZLabelsFromPromLabels(labels.FromStrings("replica", "1"))},
84+
MinTime: 100,
85+
MaxTime: 200,
86+
},
87+
},
88+
},
89+
Rules: &infopb.RulesInfo{},
90+
MetricMetadata: &infopb.MetricMetadataInfo{},
91+
Exemplars: &infopb.ExemplarsInfo{
92+
MinTime: 100,
93+
MaxTime: 200,
94+
},
95+
}
96+
97+
c := &nonPoolingCodec{}
98+
99+
_, err := c.Marshal(i)
100+
require.NoError(t, err)
101+
}

0 commit comments

Comments
 (0)