Skip to content

Commit 6471b37

Browse files
craig[bot]pav-kv
andcommitted
157105: spanset: fix and simplify mergeSpans r=stevendanna a=pav-kv The `mergeSpans` function used for `SortAndDedup` calls on `SpanSet` is not tested and not clear about the semantics when the input slice of `Span@Timestamp` has keys that are present at multiple timestamps. In the latter case, `mergeSpans` does not output a minimal / "canonical" set of spans. This does not look good because the result of this call is fed to the latch manager, i.e. this function is on the critical path for CRDB correctness / performance. Adding a test revealed a bug in this function that could result in placing a wider latch than was requested. This PR fixes this bug, adds tests, clarifies the semantics of and refactors `mergeSpans` (and the `roachpb.MergeSpans` that it is mostly a copy of) into a readable state. Epic: none Release note (bug fix): a bug in key span merging could result in placing wider latches than needed for a request, which could impose unnecessary contention. The effect of this bug hasn't been observed in the wild, and possibly never happened. 157147: roachtest: deflake splits/load/ycsb/e r=pav-kv a=pav-kv Resolves #156923 Co-authored-by: Pavel Kalinnikov <pavel@cockroachlabs.com>
3 parents 3b4cf41 + d45b333 + f215e52 commit 6471b37

File tree

17 files changed

+208
-199
lines changed

17 files changed

+208
-199
lines changed

pkg/backup/backup_job.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,7 @@ func spansForAllTableIndexes(
10371037
// Attempt to merge any contiguous spans generated from the tables and revs.
10381038
// No need to check if the spans are distinct, since some of the merged
10391039
// indexes may overlap between different revisions of the same descriptor.
1040-
mergedSpans, _ := roachpb.MergeSpans(&spans)
1040+
mergedSpans, _ := roachpb.MergeSpans(spans)
10411041

10421042
knobs := execCfg.BackupRestoreTestingKnobs
10431043
if knobs != nil && knobs.CaptureResolvedTableDescSpans != nil {

pkg/backup/restore_span_covering_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ func runTestRestoreEntryCoverForSpanAndFileCounts(
797797
completedSpans = append(completedSpans, sp)
798798
}
799799

800-
merged, _ := roachpb.MergeSpans(&completedSpans)
800+
merged, _ := roachpb.MergeSpans(completedSpans)
801801
return merged
802802
}
803803

pkg/backup/utils_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ func getSpansFromManifest(ctx context.Context, t *testing.T, backupPath string)
239239
for _, file := range backupManifest.Files {
240240
spans = append(spans, file.Span)
241241
}
242-
mergedSpans, _ := roachpb.MergeSpans(&spans)
242+
mergedSpans, _ := roachpb.MergeSpans(spans)
243243
return mergedSpans
244244
}
245245

pkg/cmd/roachtest/tests/split.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ func registerLoadSplits(r registry.Registry) {
413413
// YCSB/E has a zipfian distribution with 95% scans (limit 1k) and 5%
414414
// inserts.
415415
minimumRanges: 5,
416-
maximumRanges: 32,
416+
maximumRanges: 33,
417417
initialRangeCount: 2,
418418
load: ycsbSplitLoad{
419419
workload: "e",

pkg/kv/kvclient/kvcoord/condensable_span_set.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (s *condensableSpanSet) insert(spans ...roachpb.Span) {
6363
// The method has the side effect of sorting the set.
6464
func (s *condensableSpanSet) mergeAndSort() {
6565
oldLen := len(s.s)
66-
s.s, _ = roachpb.MergeSpans(&s.s)
66+
s.s, _ = roachpb.MergeSpans(s.s)
6767
// Recompute the size if anything has changed.
6868
if oldLen != len(s.s) {
6969
s.bytes = 0
@@ -222,7 +222,7 @@ func (s *condensableSpanSet) estimateSize(spans []roachpb.Span, mergeThresholdBy
222222
// Try harder - merge (a copy of) the existing spans with the new spans.
223223
spans = append(spans, s.s...)
224224
lenBeforeMerge := len(spans)
225-
spans, _ = roachpb.MergeSpans(&spans)
225+
spans, _ = roachpb.MergeSpans(spans)
226226
if len(spans) == lenBeforeMerge {
227227
// Nothing changed -i.e. we failed to merge any spans.
228228
return estimate

pkg/kv/kvclient/kvcoord/txn_interceptor_committer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ func mergeIntoSpans(s []roachpb.Span, ws []roachpb.SequencedWrite) ([]roachpb.Sp
404404
for i, w := range ws {
405405
m[len(s)+i] = roachpb.Span{Key: w.Key}
406406
}
407-
return roachpb.MergeSpans(&m)
407+
return roachpb.MergeSpans(m)
408408
}
409409

410410
// isTxnCommitImplicit determines whether the transaction has satisfied the

pkg/kv/kvclient/kvcoord/txn_interceptor_pipeliner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ func (tp *txnPipeliner) attachLocksToEndTxn(
485485
}
486486

487487
// Sort both sets and condense the lock spans.
488-
et.LockSpans, _ = roachpb.MergeSpans(&et.LockSpans)
488+
et.LockSpans, _ = roachpb.MergeSpans(et.LockSpans)
489489
sort.Sort(roachpb.SequencedWriteBySeq(et.InFlightWrites))
490490

491491
if log.V(3) {

pkg/kv/kvserver/batcheval/cmd_recover_txn.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ func RecoverTxn(
204204
sp := roachpb.Span{Key: w.Key}
205205
reply.RecoveredTxn.LockSpans = append(reply.RecoveredTxn.LockSpans, sp)
206206
}
207-
reply.RecoveredTxn.LockSpans, _ = roachpb.MergeSpans(&reply.RecoveredTxn.LockSpans)
207+
reply.RecoveredTxn.LockSpans, _ = roachpb.MergeSpans(reply.RecoveredTxn.LockSpans)
208208
reply.RecoveredTxn.InFlightWrites = nil
209209

210210
// Recover the transaction based on whether or not all of its writes

pkg/kv/kvserver/lockspanset/lockspanset.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (l *LockSpanSet) Add(str lock.Strength, span roachpb.Span) {
4242
// SortAndDeDup sorts the spans in the LockSpanSet and removes any duplicates.
4343
func (l *LockSpanSet) SortAndDeDup() {
4444
for st := range l.spans {
45-
l.spans[st], _ /* distinct */ = roachpb.MergeSpans(&l.spans[st])
45+
l.spans[st], _ /* distinct */ = roachpb.MergeSpans(l.spans[st])
4646
}
4747
}
4848

pkg/kv/kvserver/replica_batch_updates.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func maybeStripInFlightWrites(ba *kvpb.BatchRequest) (*kvpb.BatchRequest, error)
9292
et.LockSpans[len(origET.LockSpans)+i] = roachpb.Span{Key: w.Key}
9393
}
9494
// See below for why we set Header.DistinctSpans here.
95-
et.LockSpans, ba.Header.DistinctSpans = roachpb.MergeSpans(&et.LockSpans)
95+
et.LockSpans, ba.Header.DistinctSpans = roachpb.MergeSpans(et.LockSpans)
9696
return ba, nil
9797
}
9898
}
@@ -164,7 +164,7 @@ func maybeStripInFlightWrites(ba *kvpb.BatchRequest) (*kvpb.BatchRequest, error)
164164
// batch overlap with each other. This will have (rare) false negatives
165165
// when the in-flight writes overlap with existing lock spans, but never
166166
// false positives.
167-
et.LockSpans, ba.Header.DistinctSpans = roachpb.MergeSpans(&et.LockSpans)
167+
et.LockSpans, ba.Header.DistinctSpans = roachpb.MergeSpans(et.LockSpans)
168168
}
169169
return ba, nil
170170
}

0 commit comments

Comments
 (0)