ronantakizawa/codereview-bench huggingface dataset:
Repository: prometheus/prometheus
File: promql/bench_test.go (Go)

Code before:

	cases := []benchCase{
		{
			expr:  `rpc_request_success_total + rpc_request_error_total`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total + ON (job, instance) GROUP_LEFT rpc_request_error_total`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total AND rpc_request_error_total{instance=~"0.*"}`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total OR rpc_request_error_total{instance=~"0.*"}`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total UNLESS rpc_request_error_total{instance=~"0.*"}`,
			steps: 10000,
		},
	}

	for _, c := range cases {
		name := fmt.Sprintf("expr=%s,steps=%d", c.expr, c.steps)
		b.Run(name, func(b *testing.B) {
			ctx := context.Background()
			b.ReportAllocs()
			for range b.N {
				qry, err := engine.NewRangeQuery(
					ctx, stor, nil, c.expr,
					time.Unix(int64((numIntervals-c.steps)*10), 0),
					time.Unix(int64(numIntervals*10), 0), time.Second*10)
				if err != nil {
					b.Fatal(err)
				}
				res := qry.Exec(ctx)
				if res.Err != nil {
					b.Fatal(res.Err)
				}
				qry.Close()
			}
		})
	}
}

func BenchmarkNativeHistograms(b *testing.B) {
	testStorage := teststorage.New(b)
	defer testStorage.Close()


Review comment (suggestion):
```suggestion
		name := fmt.Sprintf("expr=%s/steps=%d", c.expr, c.steps)
```

Rationales: It unlocks https://www.bwplotka.dev/2024/go-microbenchmarks-benchstat/#newly-enabled-flow-comparing-efficiency-across-cases (kudos for using key=val syntax!)

Code after:
		Reg:        nil,
		MaxSamples: 50000000,
		Timeout:    100 * time.Second,
	}
	engine := promqltest.NewTestEngineWithOpts(b, opts)

	const interval = 10000 // 10s interval.

	// A day of data plus 10k steps.
	numIntervals := 8640 + 10000

	require.NoError(b, setupJoinQueryTestData(stor, engine, interval, numIntervals, 1000))

	for _, c := range []benchCase{
		{
			expr:  `rpc_request_success_total + rpc_request_error_total`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total + ON (job, instance) GROUP_LEFT rpc_request_error_total`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total AND rpc_request_error_total{instance=~"0.*"}`, // 0.* keeps 1/16 of UUID values
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total OR rpc_request_error_total{instance=~"0.*"}`, // 0.* keeps 1/16 of UUID values
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total UNLESS rpc_request_error_total{instance=~"0.*"}`, // 0.* keeps 1/16 of UUID values
			steps: 10000,
		},
	} {
		name := fmt.Sprintf("expr=%s/steps=%d", c.expr, c.steps)
		b.Run(name, func(b *testing.B) {
			ctx := context.Background()
			b.ReportAllocs()
			for range b.N {
				qry, err := engine.NewRangeQuery(
					ctx, stor, nil, c.expr,
					timestamp.Time(int64((numIntervals-c.steps)*10_000)),
					timestamp.Time(int64(numIntervals*10_000)),
					time.Second*10)
				require.NoError(b, err)

				res := qry.Exec(ctx)
				require.NoError(b, res.Err)

				qry.Close()
Repository: prometheus/prometheus
File: promql/bench_test.go (Go)

Code before:
			expr:  `rpc_request_success_total OR rpc_request_error_total{instance=~"0.*"}`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total UNLESS rpc_request_error_total{instance=~"0.*"}`,
			steps: 10000,
		},
	}

	for _, c := range cases {
		name := fmt.Sprintf("expr=%s,steps=%d", c.expr, c.steps)
		b.Run(name, func(b *testing.B) {
			ctx := context.Background()
			b.ReportAllocs()
			for range b.N {
				qry, err := engine.NewRangeQuery(
					ctx, stor, nil, c.expr,
					time.Unix(int64((numIntervals-c.steps)*10), 0),
					time.Unix(int64(numIntervals*10), 0), time.Second*10)
				if err != nil {
					b.Fatal(err)
				}
				res := qry.Exec(ctx)
				if res.Err != nil {
					b.Fatal(res.Err)
				}
				qry.Close()
			}
		})
	}
}

func BenchmarkNativeHistograms(b *testing.B) {
	testStorage := teststorage.New(b)
	defer testStorage.Close()

	app := testStorage.Appender(context.TODO())
	if err := generateNativeHistogramSeries(app, 3000); err != nil {
		b.Fatal(err)
	}
	if err := app.Commit(); err != nil {
		b.Fatal(err)
	}

	start := time.Unix(0, 0)
	end := start.Add(2 * time.Hour)
	step := time.Second * 30

	cases := []struct {
		name  string
		query string

Review comment (suggestion):
```suggestion
				require.NoError(b, qry.Exec(ctx)
```

Code after:
			expr:  `rpc_request_success_total + rpc_request_error_total`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total + ON (job, instance) GROUP_LEFT rpc_request_error_total`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total AND rpc_request_error_total{instance=~"0.*"}`, // 0.* keeps 1/16 of UUID values
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total OR rpc_request_error_total{instance=~"0.*"}`, // 0.* keeps 1/16 of UUID values
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total UNLESS rpc_request_error_total{instance=~"0.*"}`, // 0.* keeps 1/16 of UUID values
			steps: 10000,
		},
	} {
		name := fmt.Sprintf("expr=%s/steps=%d", c.expr, c.steps)
		b.Run(name, func(b *testing.B) {
			ctx := context.Background()
			b.ReportAllocs()
			for range b.N {
				qry, err := engine.NewRangeQuery(
					ctx, stor, nil, c.expr,
					timestamp.Time(int64((numIntervals-c.steps)*10_000)),
					timestamp.Time(int64(numIntervals*10_000)),
					time.Second*10)
				require.NoError(b, err)

				res := qry.Exec(ctx)
				require.NoError(b, res.Err)

				qry.Close()
			}
		})
	}
}

func BenchmarkNativeHistograms(b *testing.B) {
	testStorage := teststorage.New(b)
	defer testStorage.Close()

	app := testStorage.Appender(context.TODO())
	if err := generateNativeHistogramSeries(app, 3000); err != nil {
		b.Fatal(err)
	}
	if err := app.Commit(); err != nil {
		b.Fatal(err)
Repository: prometheus/prometheus
File: promql/bench_test.go (Go)

Code before:
			expr:  `rpc_request_success_total + ON (job, instance) GROUP_LEFT rpc_request_error_total`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total AND rpc_request_error_total{instance=~"0.*"}`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total OR rpc_request_error_total{instance=~"0.*"}`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total UNLESS rpc_request_error_total{instance=~"0.*"}`,
			steps: 10000,
		},
	}

	for _, c := range cases {
		name := fmt.Sprintf("expr=%s,steps=%d", c.expr, c.steps)
		b.Run(name, func(b *testing.B) {
			ctx := context.Background()
			b.ReportAllocs()
			for range b.N {
				qry, err := engine.NewRangeQuery(
					ctx, stor, nil, c.expr,
					time.Unix(int64((numIntervals-c.steps)*10), 0),
					time.Unix(int64(numIntervals*10), 0), time.Second*10)
				if err != nil {
					b.Fatal(err)
				}
				res := qry.Exec(ctx)
				if res.Err != nil {
					b.Fatal(res.Err)
				}
				qry.Close()
			}
		})
	}
}

func BenchmarkNativeHistograms(b *testing.B) {
	testStorage := teststorage.New(b)
	defer testStorage.Close()

	app := testStorage.Appender(context.TODO())
	if err := generateNativeHistogramSeries(app, 3000); err != nil {
		b.Fatal(err)
	}
	if err := app.Commit(); err != nil {
		b.Fatal(err)
	}

Review comment (suggestion):
Consistency nit: Can we use Prometheus "timestamp" notion (int64 = miliseconds unix) and then you can use `timestamp.Time(<prometheus timestmap>)` to convert to time.Time.

Code after:

	// A day of data plus 10k steps.
	numIntervals := 8640 + 10000

	require.NoError(b, setupJoinQueryTestData(stor, engine, interval, numIntervals, 1000))

	for _, c := range []benchCase{
		{
			expr:  `rpc_request_success_total + rpc_request_error_total`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total + ON (job, instance) GROUP_LEFT rpc_request_error_total`,
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total AND rpc_request_error_total{instance=~"0.*"}`, // 0.* keeps 1/16 of UUID values
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total OR rpc_request_error_total{instance=~"0.*"}`, // 0.* keeps 1/16 of UUID values
			steps: 10000,
		},
		{
			expr:  `rpc_request_success_total UNLESS rpc_request_error_total{instance=~"0.*"}`, // 0.* keeps 1/16 of UUID values
			steps: 10000,
		},
	} {
		name := fmt.Sprintf("expr=%s/steps=%d", c.expr, c.steps)
		b.Run(name, func(b *testing.B) {
			ctx := context.Background()
			b.ReportAllocs()
			for range b.N {
				qry, err := engine.NewRangeQuery(
					ctx, stor, nil, c.expr,
					timestamp.Time(int64((numIntervals-c.steps)*10_000)),
					timestamp.Time(int64(numIntervals*10_000)),
					time.Second*10)
				require.NoError(b, err)

				res := qry.Exec(ctx)
				require.NoError(b, res.Err)

				qry.Close()
			}
		})
	}
}

func BenchmarkNativeHistograms(b *testing.B) {
	testStorage := teststorage.New(b)
Repository: prometheus/prometheus
File: promql/info_test.go (Go)

Code before:
  metric{data="info", instance="a", job="1", label="value"} 0 2 3 4

# @ operator works also with info.
# Note that we pick the timestamp missing a sample, lookback should pick previous sample.
eval range from 1m to 4m step 1m info(metric @ 60)
  metric{data="info", instance="a", job="1", label="value"} 0 0 0 0

# offset operator works also with info.
eval range from 1m to 4m step 1m info(metric offset 1m)
  metric{data="info", instance="a", job="1", label="value"} 0 0 2 3

clear

load 1m
	data_metric{instance="a", job="work"}	10 20 30
	data_metric{instance="b", job="work"}	11 21 31

load 1m
	info_metric{instance="b", job="work", state="stopped"}	1 1
	info_metric{instance="b", job="work", state="running"}	_ _ 1
	info_metric{instance="a", job="work", state="running"}	1 1 1

eval range from 0 to 2m step 1m info(data_metric, {__name__="info_metric"})
	data_metric{instance="a", job="work", state="running"}	10 20 30
	data_metric{instance="b", job="work", state="stopped"}	11 21
	data_metric{instance="b", job="work", state="running"}	 _  _ 31

`, engine)
}


Review comment (suggestion):
I struggled a bit to understand the formatting, with some unexpected tabs in there etc. The following formatting is easier to understand, and more in line with the rest of the file:
```suggestion
	data_metric{instance="a", job="work"} 10 20 30
	data_metric{instance="b", job="work"} 11 21 31
	info_metric{instance="b", job="work", state="stopped"} 1 1 _
	info_metric{instance="b", job="work", state="running"} _ _ 1
	info_metric{instance="a", job="work", state="running"} 1 1 1

eval range from 0 to 2m step 1m info(data_metric, {__name__="info_metric"})
	data_metric{instance="a", job="work", state="running"} 10 20 30
	data_metric{instance="b", job="work", state="stopped"} 11 21 _
	data_metric{instance="b", job="work", state="running"} _  _ 31
```

Code after:
  metric{data="info", instance="a", job="1", label="value"} 0 2 3 4

# @ operator works also with info.
# Note that we pick the timestamp missing a sample, lookback should pick previous sample.
eval range from 1m to 4m step 1m info(metric @ 60)
  metric{data="info", instance="a", job="1", label="value"} 0 0 0 0

# offset operator works also with info.
eval range from 1m to 4m step 1m info(metric offset 1m)
  metric{data="info", instance="a", job="1", label="value"} 0 0 2 3

clear

load 1m
	data_metric{instance="a", job="work"} 10 20 30
	data_metric{instance="b", job="work"} 11 21 31
	info_metric{instance="b", job="work", state="stopped"} 1 1 _
	info_metric{instance="b", job="work", state="running"} _ _ 1
	info_metric{instance="a", job="work", state="running"} 1 1 1

eval range from 0 to 2m step 1m info(data_metric, {__name__="info_metric"})
	data_metric{instance="a", job="work", state="running"} 10 20 30
	data_metric{instance="b", job="work", state="stopped"} 11 21 _
	data_metric{instance="b", job="work", state="running"} _  _ 31

`, engine)
}
Repository: prometheus/prometheus
File: discovery/refresh/refresh.go (Go)

Code before:
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package refresh

import (
	"context"
	"errors"
	"log/slog"
	"time"

	"github.com/prometheus/common/promslog"

	"github.com/prometheus/prometheus/discovery"
	"github.com/prometheus/prometheus/discovery/targetgroup"
)

type Options struct {
	Logger              *slog.Logger
	Mech                string
	Config              string
	Interval            time.Duration
	RefreshF            func(ctx context.Context) ([]*targetgroup.Group, error)
	MetricsInstantiator discovery.RefreshMetricsInstantiator
}

// Discovery implements the Discoverer interface.
type Discovery struct {
	logger   *slog.Logger
	interval time.Duration
	refreshf func(ctx context.Context) ([]*targetgroup.Group, error)
	metrics  *discovery.RefreshMetrics
}

// NewDiscovery returns a Discoverer function that calls a refresh() function at every interval.
func NewDiscovery(opts Options) *Discovery {
	m := opts.MetricsInstantiator.Instantiate(opts.Mech, opts.Config)

	var logger *slog.Logger
	if opts.Logger == nil {
		logger = promslog.NewNopLogger()
	} else {
		logger = opts.Logger
	}

	d := Discovery{

Review comment (suggestion):
`Config` suggests to me that it's a struct.
```suggestion
	ConfigName          string
```

Code after:
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package refresh

import (
	"context"
	"errors"
	"log/slog"
	"time"

	"github.com/prometheus/common/promslog"

	"github.com/prometheus/prometheus/discovery"
	"github.com/prometheus/prometheus/discovery/targetgroup"
)

type Options struct {
	Logger              *slog.Logger
	Mech                string
	SetName             string
	Interval            time.Duration
	RefreshF            func(ctx context.Context) ([]*targetgroup.Group, error)
	MetricsInstantiator discovery.RefreshMetricsInstantiator
}

// Discovery implements the Discoverer interface.
type Discovery struct {
	logger   *slog.Logger
	interval time.Duration
	refreshf func(ctx context.Context) ([]*targetgroup.Group, error)
	metrics  *discovery.RefreshMetrics
}

// NewDiscovery returns a Discoverer function that calls a refresh() function at every interval.
func NewDiscovery(opts Options) *Discovery {
	m := opts.MetricsInstantiator.Instantiate(opts.Mech, opts.SetName)

	var logger *slog.Logger
	if opts.Logger == nil {
		logger = promslog.NewNopLogger()
	} else {
		logger = opts.Logger
	}

	d := Discovery{
Repository: prometheus/prometheus
File: model/labels/labels_stringlabels.go (Go)

Code before:
// SymbolTable is no-op, just for api parity with dedupelabels.
type SymbolTable struct{}

func NewSymbolTable() *SymbolTable { return nil }

func (*SymbolTable) Len() int { return 0 }

// NewBuilderWithSymbolTable creates a Builder, for api parity with dedupelabels.
func NewBuilderWithSymbolTable(*SymbolTable) *Builder {
	return NewBuilder(EmptyLabels())
}

// NewScratchBuilderWithSymbolTable creates a ScratchBuilder, for api parity with dedupelabels.
func NewScratchBuilderWithSymbolTable(_ *SymbolTable, n int) ScratchBuilder {
	return NewScratchBuilder(n)
}

func (*ScratchBuilder) SetSymbolTable(*SymbolTable) {
	// no-op
}

// SetUnsafeAdd allows turning on/off the assumptions that added strings are unsafe
// for reuse. ScratchBuilder implementations that do reuse strings, must clone
// the strings.
//
// Stringlabels implementation, does not reuse added strings, so this operation is noop.
func (ScratchBuilder) SetUnsafeAdd(bool) {}

// SizeOfLabels returns the approximate space required for n copies of a label.
func SizeOfLabels(name, value string, n uint64) uint64 {
	return uint64(labelSize(&Label{Name: name, Value: value})) * n
}


Review comment (suggestion):
I think it would be better to word this as "StringLabels implementation copies all strings when `Labels()` is called, so ..."

Code after:

// SymbolTable is no-op, just for api parity with dedupelabels.
type SymbolTable struct{}

func NewSymbolTable() *SymbolTable { return nil }

func (*SymbolTable) Len() int { return 0 }

// NewBuilderWithSymbolTable creates a Builder, for api parity with dedupelabels.
func NewBuilderWithSymbolTable(*SymbolTable) *Builder {
	return NewBuilder(EmptyLabels())
}

// NewScratchBuilderWithSymbolTable creates a ScratchBuilder, for api parity with dedupelabels.
func NewScratchBuilderWithSymbolTable(_ *SymbolTable, n int) ScratchBuilder {
	return NewScratchBuilder(n)
}

func (*ScratchBuilder) SetSymbolTable(*SymbolTable) {
	// no-op
}

// SetUnsafeAdd allows turning on/off the assumptions that added strings are unsafe
// for reuse. ScratchBuilder implementations that do reuse strings, must clone
// the strings.
//
// StringLabels implementation copies all strings when Labels() is called, so this operation is noop.
func (ScratchBuilder) SetUnsafeAdd(bool) {}

// SizeOfLabels returns the approximate space required for n copies of a label.
func SizeOfLabels(name, value string, n uint64) uint64 {
	return uint64(labelSize(&Label{Name: name, Value: value})) * n
}
Repository: prometheus/prometheus
File: prompb/io/prometheus/write/v2/symbols.go (Go)

Code before:
func (t *SymbolsTable) Symbols() []string {
	return t.strings
}

// Reset clears symbols table.
func (t *SymbolsTable) Reset() {
	// NOTE: Make sure to keep empty symbol.
	t.strings = t.strings[:1]
	for k := range t.symbolsMap {
		if k == "" {
			continue
		}
		delete(t.symbolsMap, k)
	}
}

// desymbolizeLabels decodes label references, with given symbols to labels.
// This function requires labelRefs to have an even number of elements (name-value pairs). It will return an error if this invariant is violated.
func desymbolizeLabels(b *labels.ScratchBuilder, labelRefs []uint32, symbols []string) (labels.Labels, error) {
	if len(labelRefs)%2 != 0 {
		return labels.EmptyLabels(), fmt.Errorf("invalid labelRefs length %d", len(labelRefs))
	}

	b.Reset()
	for i := 0; i < len(labelRefs); i += 2 {
		b.Add(symbols[labelRefs[i]], symbols[labelRefs[i+1]])
	}
	b.Sort()
	return b.Labels(), nil
}


Review comment (suggestion):
We could also check if `len(symbols) > labelRefs[i] && len(symbols) > labelRefs[i
+1] ` if we are already at this (another potential source of panics). WDYT?

```suggestion
        nameRef, valueRef :=   labelRefs[i], labelRefs[i+1] 
        if len(symbols) <= nameRef || len(symbols) <= valueRef {
          return labels.EmptyLabels(), fmt.Errorf("labelRefs [%d=%d] outside of symbols table %d", nameRef, valueRef, len(symbols))
        }
		b.Add(symbols[nameRef], symbols[valueRef])
```


Code after:
func (t *SymbolsTable) Symbols() []string {
	return t.strings
}

// Reset clears symbols table.
func (t *SymbolsTable) Reset() {
	// NOTE: Make sure to keep empty symbol.
	t.strings = t.strings[:1]
	for k := range t.symbolsMap {
		if k == "" {
			continue
		}
		delete(t.symbolsMap, k)
	}
}

// desymbolizeLabels decodes label references, with given symbols to labels.
// This function requires labelRefs to have an even number of elements (name-value pairs) and
// all references must be valid indices within the symbols table. It will return an error if
// these invariants are violated.
func desymbolizeLabels(b *labels.ScratchBuilder, labelRefs []uint32, symbols []string) (labels.Labels, error) {
	if len(labelRefs)%2 != 0 {
		return labels.EmptyLabels(), fmt.Errorf("invalid labelRefs length %d", len(labelRefs))
	}

	b.Reset()
	for i := 0; i < len(labelRefs); i += 2 {
		nameRef, valueRef := labelRefs[i], labelRefs[i+1]
		if int(nameRef) >= len(symbols) || int(valueRef) >= len(symbols) {
			return labels.EmptyLabels(), fmt.Errorf("labelRefs %d (name) = %d (value) outside of symbols table (size %d)", nameRef, valueRef, len(symbols))
		}
		b.Add(symbols[nameRef], symbols[valueRef])
	}
	b.Sort()
	return b.Labels(), nil
}
Repository: prometheus/prometheus
File: prompb/io/prometheus/write/v2/symbols.go (Go)

Code before:
// Reset clears symbols table.
func (t *SymbolsTable) Reset() {
	// NOTE: Make sure to keep empty symbol.
	t.strings = t.strings[:1]
	for k := range t.symbolsMap {
		if k == "" {
			continue
		}
		delete(t.symbolsMap, k)
	}
}

// desymbolizeLabels decodes label references, with given symbols to labels.
// This function requires labelRefs to have an even number of elements (name-value pairs) and
// all references must be valid indices within the symbols table. It will return an error if
// these invariants are violated.
func desymbolizeLabels(b *labels.ScratchBuilder, labelRefs []uint32, symbols []string) (labels.Labels, error) {
	if len(labelRefs)%2 != 0 {
		return labels.EmptyLabels(), fmt.Errorf("invalid labelRefs length %d", len(labelRefs))
	}

	b.Reset()
	for i := 0; i < len(labelRefs); i += 2 {
		nameRef, valueRef := labelRefs[i], labelRefs[i+1]
		if int(nameRef) >= len(symbols) || int(valueRef) >= len(symbols) {
			return labels.EmptyLabels(), fmt.Errorf("labelRefs [%d, %d] outside of symbols table (size %d)", nameRef, valueRef, len(symbols))
		}
		b.Add(symbols[nameRef], symbols[valueRef])
	}
	b.Sort()
	return b.Labels(), nil
}


Review comment (suggestion):
```suggestion
			return labels.EmptyLabels(), fmt.Errorf("labelRefs %d (name) = %d (value) outside of symbols table (size %d)", nameRef, valueRef, len(symbols))
```

Code after:
// Reset clears symbols table.
func (t *SymbolsTable) Reset() {
	// NOTE: Make sure to keep empty symbol.
	t.strings = t.strings[:1]
	for k := range t.symbolsMap {
		if k == "" {
			continue
		}
		delete(t.symbolsMap, k)
	}
}

// desymbolizeLabels decodes label references, with given symbols to labels.
// This function requires labelRefs to have an even number of elements (name-value pairs) and
// all references must be valid indices within the symbols table. It will return an error if
// these invariants are violated.
func desymbolizeLabels(b *labels.ScratchBuilder, labelRefs []uint32, symbols []string) (labels.Labels, error) {
	if len(labelRefs)%2 != 0 {
		return labels.EmptyLabels(), fmt.Errorf("invalid labelRefs length %d", len(labelRefs))
	}

	b.Reset()
	for i := 0; i < len(labelRefs); i += 2 {
		nameRef, valueRef := labelRefs[i], labelRefs[i+1]
		if int(nameRef) >= len(symbols) || int(valueRef) >= len(symbols) {
			return labels.EmptyLabels(), fmt.Errorf("labelRefs %d (name) = %d (value) outside of symbols table (size %d)", nameRef, valueRef, len(symbols))
		}
		b.Add(symbols[nameRef], symbols[valueRef])
	}
	b.Sort()
	return b.Labels(), nil
}