Skip to content

Commit 2e7d5a6

Browse files
craig[bot]yuzefovich
andcommitted
Merge #140477
140477: colexec: fix some benchmark issues due to a recent change r=yuzefovich a=yuzefovich In 481387c, which was supposed to be a no-op, we introduced a "closer registry" which resulted in some microbenchmark regressions. This was the case because we would reuse the same `CloserRegistry` for all iterations of the benchmark. Internally, it is represented as a single slice, so it would grow quite large, and only when tearing down the benchmark we would clean it up. This introduced some extra memory usage and allocations which would artificially slow down the benchmark and is now fixed (by resetting the registry after each benchmark run). This change logically makes sense too since it resembles how we use these objects on the main query path - the registries are pooled and reused via `vectorizedFlowCreator`. We also apply the same change to the monitor registry. All benchmarks using both registries have been adjusted accordingly. The observed regression on `BenchmarkExternalSort` is now removed: ``` name old time/op new time/op delta ExternalSort/rows=262144/cols=1/spilled=false-24 4.24ms ± 1% 3.11ms ± 2% -26.76% (p=0.000 n=10+9) name old speed new speed delta ExternalSort/rows=262144/cols=1/spilled=false-24 495MB/s ± 1% 675MB/s ± 2% +36.54% (p=0.000 n=10+9) name old alloc/op new alloc/op delta ExternalSort/rows=262144/cols=1/spilled=false-24 13.7MB ± 0% 13.7MB ± 0% +0.03% (p=0.000 n=10+9) name old allocs/op new allocs/op delta ExternalSort/rows=262144/cols=1/spilled=false-24 347 ± 0% 348 ± 0% +0.29% (p=0.000 n=10+10) ``` Epic: None Release note: None Co-authored-by: Yahor Yuzefovich <[email protected]>
2 parents d276833 + 904adf9 commit 2e7d5a6

10 files changed

+67
-20
lines changed

pkg/sql/colexec/aggregators_test.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ const (
6666
// aggType is a helper struct that allows tests to test both the ordered and
6767
// hash aggregators at the same time.
6868
type aggType struct {
69-
new func(context.Context, *colexecagg.NewAggregatorArgs) colexecop.ResettableOperator
70-
name string
71-
order ordering
69+
new func(context.Context, *colexecagg.NewAggregatorArgs) colexecop.ResettableOperator
70+
afterEachRun func() // if set, will be called at the end of each benchmark iteration
71+
name string
72+
order ordering
7273
}
7374

7475
var aggTypesWithPartial = []aggType{
@@ -1155,10 +1156,21 @@ func benchmarkAggregateFunction(
11551156
if numSameAggs != 1 {
11561157
numSameAggsSuffix = fmt.Sprintf("/numSameAggs=%d", numSameAggs)
11571158
}
1159+
afterEachRunDefault := func(b *testing.B, op colexecop.Operator) {
1160+
if err = op.(colexecop.Closer).Close(ctx); err != nil {
1161+
b.Fatal(err)
1162+
}
1163+
}
11581164
b.Run(fmt.Sprintf(
11591165
"%s/%s/%s%s/groupSize=%d%s/numInputRows=%d",
11601166
fName, agg.name, inputTypesString, numSameAggsSuffix, groupSize, distinctProbString, numInputRows),
11611167
func(b *testing.B) {
1168+
afterEachRun := afterEachRunDefault
1169+
if agg.afterEachRun != nil {
1170+
afterEachRun = func(*testing.B, colexecop.Operator) {
1171+
agg.afterEachRun()
1172+
}
1173+
}
11621174
// Simulate the scenario when the optimizer has the perfect
11631175
// estimate.
11641176
estimatedRowCount := uint64(math.Ceil(float64(numInputRows) / float64(groupSize)))
@@ -1186,9 +1198,7 @@ func benchmarkAggregateFunction(
11861198
break
11871199
}
11881200
}
1189-
if err = a.(colexecop.Closer).Close(ctx); err != nil {
1190-
b.Fatal(err)
1191-
}
1201+
afterEachRun(b, a)
11921202
source.Reset(ctx)
11931203
}
11941204
},

pkg/sql/colexec/colexecargs/closer_registry.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,11 @@ func (r *CloserRegistry) Reset() {
6161
}
6262
r.toClose = r.toClose[:0]
6363
}
64+
65+
// BenchmarkReset should only be called from benchmarks in order to prepare the
66+
// registry for the new iteration. This should be used whenever a single
67+
// registry is utilized for the whole benchmark loop.
68+
func (r *CloserRegistry) BenchmarkReset(ctx context.Context) {
69+
r.Close(ctx)
70+
r.Reset()
71+
}

pkg/sql/colexec/colexecargs/monitor_registry.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,11 @@ func (r *MonitorRegistry) Reset() {
272272
r.accounts = r.accounts[:0]
273273
r.monitors = r.monitors[:0]
274274
}
275+
276+
// BenchmarkReset should only be called from benchmarks in order to prepare the
277+
// registry for the new iteration. This should be used whenever a single
278+
// registry is utilized for the whole benchmark loop.
279+
func (r *MonitorRegistry) BenchmarkReset(ctx context.Context) {
280+
r.Close(ctx)
281+
r.Reset()
282+
}

pkg/sql/colexec/crossjoiner_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,11 @@ func BenchmarkCrossJoiner(b *testing.B) {
427427
queueCfg, cleanup := colcontainerutils.NewTestingDiskQueueCfg(b, false /* inMem */)
428428
defer cleanup()
429429
var monitorRegistry colexecargs.MonitorRegistry
430-
defer monitorRegistry.Close(ctx)
431430
var closerRegistry colexecargs.CloserRegistry
432-
defer closerRegistry.Close(ctx)
431+
afterEachRun := func() {
432+
closerRegistry.BenchmarkReset(ctx)
433+
monitorRegistry.BenchmarkReset(ctx)
434+
}
433435

434436
for _, spillForced := range []bool{false, true} {
435437
flowCtx.Cfg.TestingKnobs.ForceDiskSpill = spillForced
@@ -476,6 +478,7 @@ func BenchmarkCrossJoiner(b *testing.B) {
476478
cj.Init(ctx)
477479
for b := cj.Next(); b.Length() > 0; b = cj.Next() {
478480
}
481+
afterEachRun()
479482
}
480483
})
481484
}

pkg/sql/colexec/distinct_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ func runDistinctBenchmarks(
466466
ctx context.Context,
467467
b *testing.B,
468468
distinctConstructor func(allocator *colmem.Allocator, input colexecop.Operator, distinctCols []uint32, numOrderedCols int, typs []*types.T) (colexecop.Operator, error),
469+
afterEachRun func(),
469470
getNumOrderedCols func(nCols int) int,
470471
namePrefix string,
471472
isExternal bool,
@@ -611,6 +612,7 @@ func runDistinctBenchmarks(
611612
distinct.Init(ctx)
612613
for b := distinct.Next(); b.Length() > 0; b = distinct.Next() {
613614
}
615+
afterEachRun()
614616
}
615617
b.StopTimer()
616618
})
@@ -643,6 +645,7 @@ func BenchmarkDistinct(b *testing.B) {
643645
ctx,
644646
b,
645647
distinctConstructor,
648+
func() {},
646649
func(nCols int) int {
647650
return int(float64(nCols) * orderedColsFraction[distinctIdx])
648651
},

pkg/sql/colexec/external_distinct_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,11 @@ func BenchmarkExternalDistinct(b *testing.B) {
274274
queueCfg, cleanup := colcontainerutils.NewTestingDiskQueueCfg(b, false /* inMem */)
275275
defer cleanup()
276276
var monitorRegistry colexecargs.MonitorRegistry
277-
defer monitorRegistry.Close(ctx)
278277
var closerRegistry colexecargs.CloserRegistry
279-
defer closerRegistry.Close(ctx)
278+
afterEachRun := func() {
279+
closerRegistry.BenchmarkReset(ctx)
280+
monitorRegistry.BenchmarkReset(ctx)
281+
}
280282

281283
for _, spillForced := range []bool{false, true} {
282284
for _, maintainOrdering := range []bool{false, true} {
@@ -305,6 +307,7 @@ func BenchmarkExternalDistinct(b *testing.B) {
305307
&monitorRegistry, &closerRegistry,
306308
)
307309
},
310+
afterEachRun,
308311
func(nCols int) int {
309312
return 0
310313
},

pkg/sql/colexec/external_hash_aggregator_test.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,11 @@ func BenchmarkExternalHashAggregator(b *testing.B) {
213213
queueCfg, cleanup := colcontainerutils.NewTestingDiskQueueCfg(b, false /* inMem */)
214214
defer cleanup()
215215
var monitorRegistry colexecargs.MonitorRegistry
216-
defer monitorRegistry.Close(ctx)
217216
var closerRegistry colexecargs.CloserRegistry
218-
defer closerRegistry.Close(ctx)
217+
afterEachRun := func() {
218+
closerRegistry.BenchmarkReset(ctx)
219+
monitorRegistry.BenchmarkReset(ctx)
220+
}
219221

220222
numRows := []int{coldata.BatchSize(), 64 * coldata.BatchSize(), 4096 * coldata.BatchSize()}
221223
groupSizes := []int{1, 2, 32, 128, coldata.BatchSize()}
@@ -246,8 +248,9 @@ func BenchmarkExternalHashAggregator(b *testing.B) {
246248
// purposes of this benchmark.
247249
return colexecop.NewNoop(op)
248250
},
249-
name: fmt.Sprintf("spilled=%t", spillForced),
250-
order: unordered,
251+
afterEachRun: afterEachRun,
252+
name: fmt.Sprintf("spilled=%t", spillForced),
253+
order: unordered,
251254
},
252255
aggFn, []*types.T{types.Int}, 1 /* numGroupCol */, groupSize,
253256
0 /* distinctProb */, numInputRows, 0, /* chunkSize */

pkg/sql/colexec/external_hash_joiner_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,11 @@ func BenchmarkExternalHashJoiner(b *testing.B) {
234234
queueCfg, cleanup := colcontainerutils.NewTestingDiskQueueCfg(b, false /* inMem */)
235235
defer cleanup()
236236
var monitorRegistry colexecargs.MonitorRegistry
237-
defer monitorRegistry.Close(ctx)
238237
var closerRegistry colexecargs.CloserRegistry
239-
defer closerRegistry.Close(ctx)
238+
afterEachRun := func() {
239+
closerRegistry.BenchmarkReset(ctx)
240+
monitorRegistry.BenchmarkReset(ctx)
241+
}
240242

241243
nCols := 4
242244
for _, typ := range []*types.T{types.Int, types.Bytes} {
@@ -289,6 +291,7 @@ func BenchmarkExternalHashJoiner(b *testing.B) {
289291
hj.Init(ctx)
290292
for b := hj.Next(); b.Length() > 0; b = hj.Next() {
291293
}
294+
afterEachRun()
292295
}
293296
})
294297
}

pkg/sql/colexec/external_sort_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,11 @@ func BenchmarkExternalSort(b *testing.B) {
227227
queueCfg, cleanup := colcontainerutils.NewTestingDiskQueueCfg(b, false /* inMem */)
228228
defer cleanup()
229229
var monitorRegistry colexecargs.MonitorRegistry
230-
defer monitorRegistry.Close(ctx)
231230
var closerRegistry colexecargs.CloserRegistry
232-
defer closerRegistry.Close(ctx)
231+
afterEachRun := func() {
232+
closerRegistry.BenchmarkReset(ctx)
233+
monitorRegistry.BenchmarkReset(ctx)
234+
}
233235

234236
for _, nBatches := range []int{1 << 1, 1 << 4, 1 << 8} {
235237
for _, nCols := range []int{1, 2, 4} {
@@ -280,6 +282,7 @@ func BenchmarkExternalSort(b *testing.B) {
280282
sorter.Init(ctx)
281283
for out := sorter.Next(); out.Length() != 0; out = sorter.Next() {
282284
}
285+
afterEachRun()
283286
require.Equal(b, spillForced, spilled, fmt.Sprintf(
284287
"expected: spilled=%t\tactual: spilled=%t", spillForced, spilled,
285288
))

pkg/sql/colflow/colbatch_scan_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,11 @@ func BenchmarkColBatchScan(b *testing.B) {
159159
evalCtx := eval.MakeTestingEvalContext(s.ClusterSettings())
160160
defer evalCtx.Stop(ctx)
161161
var monitorRegistry colexecargs.MonitorRegistry
162-
defer monitorRegistry.Close(ctx)
163162
var closerRegistry colexecargs.CloserRegistry
164-
defer closerRegistry.Close(ctx)
163+
afterEachRun := func() {
164+
closerRegistry.BenchmarkReset(ctx)
165+
monitorRegistry.BenchmarkReset(ctx)
166+
}
165167

166168
flowCtx := execinfra.FlowCtx{
167169
EvalCtx: &evalCtx,
@@ -197,6 +199,7 @@ func BenchmarkColBatchScan(b *testing.B) {
197199
}
198200
}
199201
b.StopTimer()
202+
afterEachRun()
200203
}
201204
})
202205
}

0 commit comments

Comments
 (0)