diff --git a/CHANGELOG.md b/CHANGELOG.md index bf05db5ba0..6d3c04387a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ * [ENHANCEMENT] Distributor: Add HMAC-SHA256 stream authentication for `PushStream` via `-distributor.sign-write-requests-keys`. #7475 * [ENHANCEMENT] Instrument Ingester CPU profile with source for read APIs. #7494 * [ENHANCEMENT] Ingester: Convert expanded postings cache from FIFO to LRU eviction to retain frequently-queried entries under memory pressure. #7510 +* [ENHANCEMENT] Querier: Detach series label and chunk data from gRPC unmarshal buffers in store-gateway streaming path, allowing the Go GC to reclaim receive buffers. #7519 * [BUGFIX] Querier: Fix queryWithRetry and labelsWithRetry returning (nil, nil) on cancelled context by propagating ctx.Err(). #7370 * [BUGFIX] Metrics Helper: Fix non-deterministic bucket order in merged histograms by sorting buckets after map iteration, matching Prometheus client library behavior. #7380 * [BUGFIX] Distributor: Return HTTP 401 Unauthorized when tenant ID resolution fails in the Prometheus Remote Write 2.0 path. #7389 diff --git a/pkg/querier/blocks_store_queryable.go b/pkg/querier/blocks_store_queryable.go index f9deca3b9b..6902fcde5e 100644 --- a/pkg/querier/blocks_store_queryable.go +++ b/pkg/querier/blocks_store_queryable.go @@ -29,6 +29,7 @@ import ( "github.com/thanos-io/thanos/pkg/pool" thanosquery "github.com/thanos-io/thanos/pkg/query" "github.com/thanos-io/thanos/pkg/store/hintspb" + "github.com/thanos-io/thanos/pkg/store/labelpb" "github.com/thanos-io/thanos/pkg/store/storepb" "github.com/thanos-io/thanos/pkg/strutil" "go.uber.org/atomic" @@ -675,6 +676,8 @@ func (q *blocksStoreQuerier) fetchSeriesFromStores( myQueriedBlocks := []ulid.ULID(nil) processSeries := func(s *storepb.Series) error { + // Detach series data from the gRPC unmarshal buffer so that it can be freed. + detachSeriesFromBuffer(s) mySeries = append(mySeries, s) // Add series fingerprint to query limiter; will return error if we are over the limit @@ -1189,6 +1192,17 @@ func convertBlockHintsToULIDs(hints []hintspb.Block) ([]ulid.ULID, error) { return res, nil } +// detachSeriesFromBuffer re-allocates label strings and chunk data byte slices +// so that the series no longer references the gRPC unmarshal buffer. +func detachSeriesFromBuffer(s *storepb.Series) { + labelpb.ReAllocZLabelsStrings(&s.Labels, true) + for i := range s.Chunks { + if s.Chunks[i].Raw != nil && len(s.Chunks[i].Raw.Data) > 0 { + s.Chunks[i].Raw.Data = append([]byte(nil), s.Chunks[i].Raw.Data...) + } + } +} + // countChunkBytes returns the size of the chunks making up the provided series in bytes func countChunkBytes(series ...*storepb.Series) (count int) { for _, s := range series {