Skip to content

Commit 0c9c77f

Browse files
craig[bot]andyyang890
andcommitted
Merge #154341
154341: changefeedccl/resolvedspan: benchmark frontier per-table tracking r=KeithCh,asg0451 a=andyyang890 Fixes #152111 --- This patch adds a new benchmark for frontier per-table tracking. Results when I run the benchmark on my laptop: ``` goos: darwin goarch: arm64 cpu: Apple M1 Pro BenchmarkFrontierPerTableTracking/system/aggregator/per-table-tracking=false BenchmarkFrontierPerTableTracking/system/aggregator/per-table-tracking=false 11734448 93.39 ns/op 0 B/op 0 allocs/op BenchmarkFrontierPerTableTracking/system/aggregator/per-table-tracking=true BenchmarkFrontierPerTableTracking/system/aggregator/per-table-tracking=true 6423613 171.1 ns/op 16 B/op 2 allocs/op BenchmarkFrontierPerTableTracking/system/coordinator/per-table-tracking=false BenchmarkFrontierPerTableTracking/system/coordinator/per-table-tracking=false 14056830 87.45 ns/op 0 B/op 0 allocs/op BenchmarkFrontierPerTableTracking/system/coordinator/per-table-tracking=true BenchmarkFrontierPerTableTracking/system/coordinator/per-table-tracking=true 7310874 157.4 ns/op 16 B/op 2 allocs/op BenchmarkFrontierPerTableTracking/tenant/aggregator/per-table-tracking=false BenchmarkFrontierPerTableTracking/tenant/aggregator/per-table-tracking=false 14520753 82.53 ns/op 0 B/op 0 allocs/op BenchmarkFrontierPerTableTracking/tenant/aggregator/per-table-tracking=true BenchmarkFrontierPerTableTracking/tenant/aggregator/per-table-tracking=true 7783419 160.1 ns/op 16 B/op 2 allocs/op BenchmarkFrontierPerTableTracking/tenant/coordinator/per-table-tracking=false BenchmarkFrontierPerTableTracking/tenant/coordinator/per-table-tracking=false 14832232 83.03 ns/op 0 B/op 0 allocs/op BenchmarkFrontierPerTableTracking/tenant/coordinator/per-table-tracking=true BenchmarkFrontierPerTableTracking/tenant/coordinator/per-table-tracking=true 8280913 164.1 ns/op 16 B/op 2 allocs/op ``` From profiling, the allocs and some of the slowdown when per-table tracking is on comes from constructing the full table spans. We could consider caching them in the future if we see a need. Release note: None Co-authored-by: Andy Yang <[email protected]>
2 parents 1c18131 + f7159b1 commit 0c9c77f

File tree

3 files changed

+166
-1
lines changed

3 files changed

+166
-1
lines changed

pkg/ccl/changefeedccl/resolvedspan/BUILD.bazel

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,31 @@ go_library(
2424

2525
go_test(
2626
name = "resolvedspan_test",
27-
srcs = ["frontier_test.go"],
27+
srcs = [
28+
"frontier_test.go",
29+
"main_test.go",
30+
],
2831
deps = [
2932
":resolvedspan",
33+
"//pkg/base",
34+
"//pkg/ccl",
3035
"//pkg/jobs/jobspb",
3136
"//pkg/keys",
3237
"//pkg/roachpb",
38+
"//pkg/security/securityassets",
39+
"//pkg/security/securitytest",
40+
"//pkg/server",
3341
"//pkg/sql/catalog/descpb",
3442
"//pkg/testutils",
43+
"//pkg/testutils/serverutils",
44+
"//pkg/testutils/sqlutils",
45+
"//pkg/testutils/testcluster",
3546
"//pkg/util/hlc",
3647
"//pkg/util/leaktest",
3748
"//pkg/util/log",
3849
"//pkg/util/randutil",
3950
"//pkg/util/span",
51+
"//pkg/util/timeutil",
4052
"@com_github_cockroachdb_errors//:errors",
4153
"@com_github_stretchr_testify//require",
4254
],

pkg/ccl/changefeedccl/resolvedspan/frontier_test.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,27 @@
66
package resolvedspan_test
77

88
import (
9+
"context"
10+
"fmt"
911
"iter"
1012
"testing"
13+
"time"
1114

15+
"github.com/cockroachdb/cockroach/pkg/base"
1216
"github.com/cockroachdb/cockroach/pkg/ccl/changefeedccl/resolvedspan"
1317
"github.com/cockroachdb/cockroach/pkg/jobs/jobspb"
1418
"github.com/cockroachdb/cockroach/pkg/keys"
1519
"github.com/cockroachdb/cockroach/pkg/roachpb"
1620
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
1721
"github.com/cockroachdb/cockroach/pkg/testutils"
22+
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
23+
"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
1824
"github.com/cockroachdb/cockroach/pkg/util/hlc"
1925
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
2026
"github.com/cockroachdb/cockroach/pkg/util/log"
2127
"github.com/cockroachdb/cockroach/pkg/util/randutil"
2228
"github.com/cockroachdb/cockroach/pkg/util/span"
29+
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
2330
"github.com/cockroachdb/errors"
2431
"github.com/stretchr/testify/require"
2532
)
@@ -172,6 +179,7 @@ func TestCoordinatorFrontier(t *testing.T) {
172179
}
173180

174181
type frontier interface {
182+
AddSpansAt(startAt hlc.Timestamp, spans ...roachpb.Span) error
175183
Frontier() hlc.Timestamp
176184
ForwardResolvedSpan(jobspb.ResolvedSpan) (bool, error)
177185
InBackfill(jobspb.ResolvedSpan) bool
@@ -530,3 +538,120 @@ func TestFrontierForwardFullTableSpan(t *testing.T) {
530538
require.Equal(t, targetTimestamp, f.Frontier())
531539
})
532540
}
541+
542+
func BenchmarkFrontierPerTableTracking(b *testing.B) {
543+
defer leaktest.AfterTest(b)()
544+
defer log.Scope(b).Close(b)
545+
546+
ctx := context.Background()
547+
rng, _ := randutil.NewTestRand()
548+
549+
// Generate a random span iteration order that's the same for all
550+
// sub-benchmarks.
551+
const numSpans = 100
552+
order := make([]int, numSpans)
553+
for i := range numSpans {
554+
order[i] = i
555+
}
556+
rng.Shuffle(numSpans, func(i, j int) {
557+
order[i], order[j] = order[j], order[i]
558+
})
559+
560+
for _, tenantType := range []string{"system", "tenant"} {
561+
for _, frontierType := range []string{"aggregator", "coordinator"} {
562+
for _, perTableTracking := range []bool{false, true} {
563+
b.Run(
564+
fmt.Sprintf("%s/%s/per-table-tracking=%t", tenantType, frontierType, perTableTracking),
565+
func(b *testing.B) {
566+
// Start the server.
567+
srv, db, _ := serverutils.StartServer(b, base.TestServerArgs{
568+
DefaultTestTenant: base.TestControlsTenantsExplicitly,
569+
})
570+
defer srv.Stopper().Stop(ctx)
571+
572+
// Get a SQL connection/codec for the tenant type.
573+
sqlDB, codec := func() (*sqlutils.SQLRunner, keys.SQLCodec) {
574+
switch tenantType {
575+
case "system":
576+
return sqlutils.MakeSQLRunner(db), keys.SystemSQLCodec
577+
case "tenant":
578+
tenantID := roachpb.MinTenantID
579+
_, tenantDB := serverutils.StartTenant(b, srv, base.TestTenantArgs{
580+
TenantID: tenantID,
581+
})
582+
return sqlutils.MakeSQLRunner(tenantDB), keys.MakeSQLCodec(tenantID)
583+
default:
584+
panic("unreachable")
585+
}
586+
}()
587+
588+
// Create a table and split it into multiple spans.
589+
sqlDB.Exec(b, `CREATE TABLE foo (id INT PRIMARY KEY)`)
590+
sqlDB.Exec(b, fmt.Sprintf(
591+
`ALTER TABLE foo SPLIT AT SELECT generate_series(10, %d, 10)`, (numSpans-1)*10))
592+
593+
var fooTableID uint32
594+
sqlDB.QueryRow(b, `SELECT 'foo'::regclass::oid::int`).Scan(&fooTableID)
595+
fooSpan := codec.TableSpan(fooTableID)
596+
597+
// Collect all the spans.
598+
var spans roachpb.Spans
599+
rows := sqlDB.Query(b, `SELECT raw_start_key, raw_end_key
600+
FROM [SHOW RANGES FROM TABLE foo WITH KEYS]`)
601+
for rows.Next() {
602+
var startKey, endKey roachpb.Key
603+
err := rows.Scan(&startKey, &endKey)
604+
require.NoError(b, err)
605+
sp := roachpb.Span{Key: startKey, EndKey: endKey}
606+
spans = append(spans, fooSpan.Intersect(sp))
607+
}
608+
require.Len(b, spans, numSpans)
609+
610+
now := makeTS(timeutil.Now().Unix())
611+
612+
// Create the frontier and add all the spans.
613+
f, err := func() (frontier, error) {
614+
switch frontierType {
615+
case "aggregator":
616+
return resolvedspan.NewAggregatorFrontier(
617+
now,
618+
now,
619+
codec,
620+
perTableTracking,
621+
)
622+
case "coordinator":
623+
return resolvedspan.NewCoordinatorFrontier(
624+
now,
625+
now,
626+
codec,
627+
perTableTracking,
628+
)
629+
default:
630+
panic("unreachable")
631+
}
632+
}()
633+
require.NoError(b, err)
634+
require.NoError(b, f.AddSpansAt(now, spans...))
635+
636+
// Main benchmark loop: forward (shuffled) spans in a loop.
637+
b.ResetTimer()
638+
for n := range b.N {
639+
ts := now.AddDuration(time.Second)
640+
i := n % len(spans)
641+
_, err := f.ForwardResolvedSpan(jobspb.ResolvedSpan{
642+
Span: spans[order[i]],
643+
Timestamp: ts,
644+
})
645+
if err != nil {
646+
b.Fatalf("error forwarding: %v", err)
647+
}
648+
}
649+
b.StopTimer()
650+
651+
// Make sure the compiler doesn't optimize away the forwards.
652+
require.True(b, now.LessEq(f.Frontier()))
653+
})
654+
}
655+
}
656+
}
657+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2025 The Cockroach Authors.
2+
//
3+
// Use of this software is governed by the CockroachDB Software License
4+
// included in the /LICENSE file.
5+
6+
package resolvedspan_test
7+
8+
import (
9+
"os"
10+
"testing"
11+
12+
"github.com/cockroachdb/cockroach/pkg/ccl"
13+
"github.com/cockroachdb/cockroach/pkg/security/securityassets"
14+
"github.com/cockroachdb/cockroach/pkg/security/securitytest"
15+
"github.com/cockroachdb/cockroach/pkg/server"
16+
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
17+
"github.com/cockroachdb/cockroach/pkg/testutils/testcluster"
18+
"github.com/cockroachdb/cockroach/pkg/util/randutil"
19+
)
20+
21+
func TestMain(m *testing.M) {
22+
defer ccl.TestingEnableEnterprise()()
23+
securityassets.SetLoader(securitytest.EmbeddedAssets)
24+
randutil.SeedForTests()
25+
serverutils.InitTestServerFactory(server.TestServerFactory)
26+
serverutils.InitTestClusterFactory(testcluster.TestClusterFactory)
27+
os.Exit(m.Run())
28+
}

0 commit comments

Comments
 (0)