Skip to content

Commit 9bdf947

Browse files
tbgroachdev-claude
andcommitted
roachtest: register perturbation/long/restart
Register perturbation/long/restart as a Weekly variant of the existing perturbation/full/restart test, with a 2h fill duration so the target node accumulates enough behind it during the perturbation to make recovery non-trivial. This replaces kv/restart/nodes=12 (removed in the previous commit) — at lower write intensity than the test it replaces (50/50 r/w with 4KB blocks vs 90% writes with 8KB blocks on PD-SSD), but relying on the perturbation framework's baseline/perturbation/recovery roachperf instrumentation to surface regressions. The new addLong() helper is wired only for restart{} in RegisterTests rather than from inside register(), so other perturbations (backup, intents, decommission, ...) don't grow long variants by default. Future heavyweight perturbations can opt in the same way. Touches #170047. Epic: none Release note: None Co-Authored-By: roachdev-claude <roachdev-claude-bot@cockroachlabs.com>
1 parent 0959def commit 9bdf947

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

pkg/cmd/roachtest/tests/perturbation/framework.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ func RegisterTests(r registry.Registry) {
393393
const skippedByBankruptcy = "#149662"
394394

395395
register(r, restart{}, notSkipped)
396+
addLong(r, restart{})
396397
register(r, backup{}, notSkipped)
397398

398399
// TODO(ssd): We skipped the majority of these tests so that we can focus on
@@ -565,6 +566,67 @@ func addFull(r registry.Registry, p perturbation, skipReason string) {
565566
})
566567
}
567568

569+
// addLong registers a heavyweight variant of a perturbation test that runs
570+
// significantly longer than addFull. It is intended for cases where the
571+
// perturbation only becomes interesting at scale (e.g. a restart that needs a
572+
// non-trivial backlog to surface IO-overload behavior on recovery), and
573+
// belongs to the Weekly suite to keep the nightly footprint small. Individual
574+
// callers can override variations fields after p.setup() to tune what "long"
575+
// means for their perturbation; the timeout below is sized for the longest
576+
// expected fill-plus-perturbation we currently configure.
577+
//
578+
// What the long fill buys, and what it does not:
579+
//
580+
// The 2h fill duration grows the LSM and range count on the surviving nodes
581+
// so that ongoing compactions, snapshot generation, and lease bookkeeping at
582+
// the time of the perturbation reflect a non-trivial steady-state cluster,
583+
// rather than a freshly-initialized one. It does NOT enlarge the raft gap
584+
// the perturbed node has to close on recovery -- that gap is set by
585+
// perturbationDuration (default 10 minutes) and the cluster's write rate
586+
// during the measurement phase.
587+
//
588+
// Napkin math for the restart variant on the default 12-node, 16 vcpu,
589+
// localSSD spec with 50/50 r/w (50% follower-reads), 4 KiB blocks, and
590+
// splits=10000: cluster max throughput measures around 80k ops/s, so at
591+
// ratioOfMax=0.5 the measurement workload sustains ~20k writes/s. A 10
592+
// minute downtime therefore produces ~12 GiB of cluster-wide raft data
593+
// destined for the down node's ranges. With ~25% of replicas on a
594+
// 12-node RF=3 cluster across 10000 splits, the down node owns ~2500
595+
// ranges, so the average per-range raft log accumulated against it is
596+
// ~5 MiB. That sits below RaftLogTruncationThreshold (16 MiB; see
597+
// pkg/base/config.go), so most ranges should recover via log replay
598+
// rather than raft snapshots; if the per-range write skew, the cluster
599+
// throughput, or perturbationDuration grow, the average will cross that
600+
// threshold and the cost mix shifts toward snapshot ingest.
601+
func addLong(r registry.Registry, p perturbation) {
602+
v := p.setup()
603+
v.fillDuration = 2 * time.Hour
604+
v = v.finishSetup()
605+
r.Add(registry.TestSpec{
606+
Name: fmt.Sprintf("perturbation/long/%s", v.perturbationName()),
607+
CompatibleClouds: v.cloud,
608+
Suites: registry.Suites(registry.Weekly),
609+
Owner: registry.OwnerKV,
610+
Cluster: v.makeClusterSpec(),
611+
Leases: v.leaseType,
612+
Benchmark: true,
613+
// The expected runtime is around 2h45m (2h fill + 10m perturbation +
614+
// validation/recovery windows + teardown). The timeout is set well
615+
// above that — it is a backstop for pathological cases (everything
616+
// seizing up in a way that does not surface as a test failure) and
617+
// not a target.
618+
Timeout: 6 * time.Hour,
619+
// The 2h fill produces enough data that the post-test replica
620+
// divergence check exceeds its 20m budget, mirroring the carve-out
621+
// for large block sizes in pkg/cmd/roachtest/tests/kv.go (see
622+
// #141007). The divergence-check timeout is logged but does not
623+
// fail the test; we skip it explicitly to keep the artifact clean.
624+
SkipPostValidations: registry.PostValidationReplicaDivergence,
625+
PostProcessPerfMetrics: perturbationDefaultProcessFunction,
626+
Run: v.runTest,
627+
})
628+
}
629+
568630
func addDev(r registry.Registry, p perturbation) {
569631
v := p.setup()
570632
// Dev tests never fail on latency increases.

0 commit comments

Comments
 (0)