Skip to content

Commit f033993

Browse files
committed
Add benchmark
Signed-off-by: SungJin1212 <tjdwls1201@gmail.com>
1 parent 91af7e7 commit f033993

2 files changed

Lines changed: 168 additions & 1 deletion

File tree

integration/parquet_store_gateway_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func TestParquetBucketStore_ProjectionHint(t *testing.T) {
5050
"-blocks-storage.bucket-store.bucket-store-type": "parquet",
5151

5252
// Set query-ingesters-within to 1h so queries older than 1h don't hit ingesters
53-
"-querier.query-ingesters-within": "1h",
53+
"-limits.query-ingesters-within": "1h",
5454

5555
// Configure Parquet Converter
5656
"-parquet-converter.enabled": "true",

pkg/storegateway/parquet_bucket_store_bench_test.go

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,173 @@ import (
4040
"github.com/cortexproject/cortex/pkg/util/validation"
4141
)
4242

43+
// BenchmarkParquetBucketStore_ProjectionHints compares query performance
44+
// with and without projectionHints enabled.
45+
func BenchmarkParquetBucketStore_ProjectionHints(b *testing.B) {
46+
seriesNum := []int{100, 1000, 10000}
47+
samplePerSeries := 100
48+
49+
// projectionLabels is the subset of labels requested via projection hints.
50+
// The test data contains: __name__, idx, job, instance
51+
projectionLabels := []string{"job"}
52+
53+
for _, numSeries := range seriesNum {
54+
b.Run(fmt.Sprintf("series_%d", numSeries), func(b *testing.B) {
55+
ctx := context.Background()
56+
tmpDir := b.TempDir()
57+
storageDir := filepath.Join(tmpDir, "storage")
58+
dataDir := filepath.Join(tmpDir, "data")
59+
userID := "user-1"
60+
61+
storageCfg := cortex_tsdb.BlocksStorageConfig{
62+
UsersScanner: users.UsersScannerConfig{
63+
Strategy: users.UserScanStrategyList,
64+
UpdateInterval: time.Second,
65+
},
66+
Bucket: bucket.Config{
67+
Backend: "filesystem",
68+
Filesystem: filesystem.Config{
69+
Directory: storageDir,
70+
},
71+
},
72+
BucketStore: cortex_tsdb.BucketStoreConfig{
73+
SyncDir: filepath.Join(tmpDir, "sync"),
74+
BucketStoreType: "parquet",
75+
BlockDiscoveryStrategy: string(cortex_tsdb.RecursiveDiscovery),
76+
},
77+
}
78+
79+
bucketClient, err := bucket.NewClient(ctx, storageCfg.Bucket, nil, "test", log.NewNopLogger(), prometheus.NewRegistry())
80+
require.NoError(b, err)
81+
82+
blockID := prepareParquetBlock(b, ctx, storageCfg, bucketClient, dataDir, userID, numSeries, samplePerSeries)
83+
84+
startGRPCServer := func(honorProjectionHints bool) (storepb.StoreClient, func()) {
85+
cfg := storageCfg
86+
cfg.BucketStore.HonorProjectionHints = honorProjectionHints
87+
88+
reg := prometheus.NewPedanticRegistry()
89+
stores, err := NewBucketStores(cfg, NewNoShardingStrategy(log.NewNopLogger(), nil), objstore.WithNoopInstr(bucketClient), defaultLimitsOverrides(nil), mockLoggingLevel(), log.NewNopLogger(), reg)
90+
require.NoError(b, err)
91+
92+
listener, err := net.Listen("tcp", "localhost:0")
93+
require.NoError(b, err)
94+
95+
gRPCServer := grpc.NewServer(
96+
grpc.StreamInterceptor(middleware.StreamServerUserHeaderInterceptor),
97+
)
98+
storepb.RegisterStoreServer(gRPCServer, stores)
99+
100+
go func() {
101+
if err := gRPCServer.Serve(listener); err != nil && err != grpc.ErrServerStopped {
102+
b.Error(err)
103+
}
104+
}()
105+
106+
conn, err := grpc.NewClient(listener.Addr().String(),
107+
grpc.WithTransportCredentials(insecure.NewCredentials()),
108+
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32)),
109+
)
110+
require.NoError(b, err)
111+
112+
return storepb.NewStoreClient(conn), func() {
113+
_ = conn.Close()
114+
gRPCServer.Stop()
115+
}
116+
}
117+
118+
// Benchmark without projectionHints (full scan)
119+
b.Run("without_projection_hints", func(b *testing.B) {
120+
client, stop := startGRPCServer(false)
121+
defer stop()
122+
123+
b.ReportAllocs()
124+
for b.Loop() {
125+
benchmarkProjectionHints(b, client, userID, blockID, numSeries, nil)
126+
}
127+
})
128+
129+
// Benchmark with projectionHints enabled and projection labels specified
130+
b.Run("with_projection_hints", func(b *testing.B) {
131+
client, stop := startGRPCServer(true)
132+
defer stop()
133+
134+
b.ReportAllocs()
135+
for b.Loop() {
136+
benchmarkProjectionHints(b, client, userID, blockID, numSeries, projectionLabels)
137+
}
138+
})
139+
})
140+
}
141+
}
142+
143+
func benchmarkProjectionHints(b *testing.B, client storepb.StoreClient, userID, blockID string, expectedSeries int, projectionLabels []string) {
144+
b.Helper()
145+
146+
ctx := grpcMetadata.NewOutgoingContext(context.Background(), grpcMetadata.Pairs(cortex_tsdb.TenantIDExternalLabel, userID))
147+
ctx, err := user.InjectIntoGRPCRequest(user.InjectOrgID(ctx, userID))
148+
require.NoError(b, err)
149+
150+
hintMatchers := []storepb.LabelMatcher{
151+
{
152+
Type: storepb.LabelMatcher_RE,
153+
Name: block.BlockIDLabel,
154+
Value: blockID,
155+
},
156+
}
157+
158+
dataMatchers := []storepb.LabelMatcher{
159+
{
160+
Type: storepb.LabelMatcher_RE,
161+
Name: "__name__",
162+
Value: ".+",
163+
},
164+
}
165+
166+
hints := &hintspb.SeriesRequestHints{
167+
BlockMatchers: hintMatchers,
168+
}
169+
hintsAny, err := types.MarshalAny(hints)
170+
require.NoError(b, err)
171+
172+
req := &storepb.SeriesRequest{
173+
MinTime: 0,
174+
MaxTime: math.MaxInt64,
175+
Matchers: dataMatchers,
176+
ResponseBatchSize: 1000,
177+
Hints: hintsAny,
178+
}
179+
180+
if len(projectionLabels) > 0 {
181+
req.QueryHints = &storepb.QueryHints{
182+
ProjectionInclude: true,
183+
ProjectionLabels: projectionLabels,
184+
}
185+
}
186+
187+
stream, err := client.Series(ctx, req)
188+
require.NoError(b, err)
189+
190+
got := 0
191+
for {
192+
resp, err := stream.Recv()
193+
if err == io.EOF {
194+
break
195+
}
196+
require.NoError(b, err)
197+
198+
if series := resp.GetSeries(); series != nil {
199+
got++
200+
} else if batch := resp.GetBatch(); batch != nil {
201+
got += len(batch.Series)
202+
}
203+
}
204+
205+
if got != expectedSeries {
206+
b.Fatalf("expected %d series, got %d", expectedSeries, got)
207+
}
208+
}
209+
43210
func BenchmarkParquetBucketStore_SeriesBatch(b *testing.B) {
44211
seriesNum := []int{100, 1000, 10000, 100000}
45212
samplePerSeries := 100

0 commit comments

Comments
 (0)