Skip to content

Commit b9a9506

Browse files
craig[bot]jbowens
andcommitted
Merge #149909
149909: storage: refactor computeStatsForIterWithVisitors r=sumeerbhola a=jbowens Refactor computeStatsForIterWithVisitors to make the control flow more obvious and document the conditions more completely. This refactor duplicates some code by extracting the case for non-MVCC values. This duplication leads to more understandable code through removing deeply nested conditional state. Epic: none Informs #149835. Release note: None Co-authored-by: Jackson Owens <[email protected]>
2 parents 6f79180 + d1ae979 commit b9a9506

File tree

1 file changed

+103
-84
lines changed

1 file changed

+103
-84
lines changed

pkg/storage/mvcc.go

Lines changed: 103 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -7426,6 +7426,52 @@ func computeStatsForIterWithVisitors(
74267426
implicitMeta := isValue && !bytes.Equal(unsafeKey.Key, prevKey)
74277427
prevKey = append(prevKey[:0], unsafeKey.Key...)
74287428

7429+
if !isValue {
7430+
// The key-value is not a MVCC value (i.e., the key has a zero
7431+
// timestamp). The stats accounting for non-MVCC values is simpler.
7432+
metaKeySize := int64(len(unsafeKey.Key)) + 1
7433+
metaValSize := int64(iter.ValueLen())
7434+
totalBytes := metaKeySize + metaValSize
7435+
first = true
7436+
7437+
if isSys {
7438+
// The key is an internal system key. It contributes to
7439+
// Sys{Bytes,Count} instead of {Key,Val}{Count,Bytes}.
7440+
ms.SysBytes += totalBytes
7441+
ms.SysCount++
7442+
if isAbortSpanKey(unsafeKey.Key) {
7443+
ms.AbortSpanBytes += totalBytes
7444+
}
7445+
continue
7446+
}
7447+
// A non-system key. Decode the value as a MVCCMetadata.
7448+
v, err := iter.UnsafeValue()
7449+
if err != nil {
7450+
return enginepb.MVCCStats{}, err
7451+
}
7452+
if err := protoutil.Unmarshal(v, &meta); err != nil {
7453+
return ms, errors.Wrap(err, "unable to decode MVCCMetadata")
7454+
}
7455+
if meta.Deleted {
7456+
// First value is deleted, so it's GC'able; add meta key & value
7457+
// bytes to age stat.
7458+
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - meta.Timestamp.WallTime/1e9)
7459+
} else {
7460+
ms.LiveBytes += totalBytes
7461+
ms.LiveCount++
7462+
}
7463+
ms.KeyBytes += metaKeySize
7464+
ms.ValBytes += metaValSize
7465+
ms.KeyCount++
7466+
if meta.IsInline() {
7467+
ms.ValCount++
7468+
}
7469+
continue
7470+
}
7471+
7472+
// The key-value is a MVCC value (i.e., the key has a non-zero
7473+
// timestamp).
7474+
74297475
// Find the closest range tombstone above the point key. Range tombstones
74307476
// cannot exist above intents, and are undefined across inline values, so we
74317477
// only take them into account for versioned values.
@@ -7435,25 +7481,15 @@ func computeStatsForIterWithVisitors(
74357481
// stack as we descend through older versions, resetting once we hit a new
74367482
// key.
74377483
var nextRangeTombstone hlc.Timestamp
7438-
if isValue {
7439-
if !rangeTombstones.IsEmpty() && unsafeKey.Timestamp.LessEq(rangeTombstones.Newest()) {
7440-
if v, ok := rangeTombstones.FirstAtOrAbove(unsafeKey.Timestamp); ok {
7441-
nextRangeTombstone = v.Timestamp
7442-
}
7484+
if !rangeTombstones.IsEmpty() && unsafeKey.Timestamp.LessEq(rangeTombstones.Newest()) {
7485+
if v, ok := rangeTombstones.FirstAtOrAbove(unsafeKey.Timestamp); ok {
7486+
nextRangeTombstone = v.Timestamp
74437487
}
74447488
}
74457489

7446-
var valueLen int
7447-
var mvccValueIsTombstone bool
7448-
if isValue {
7449-
// MVCC value
7450-
var err error
7451-
valueLen, mvccValueIsTombstone, err = iter.MVCCValueLenAndIsTombstone()
7452-
if err != nil {
7453-
return enginepb.MVCCStats{}, errors.Wrap(err, "unable to decode MVCCValue")
7454-
}
7455-
} else {
7456-
valueLen = iter.ValueLen()
7490+
valueLen, mvccValueIsTombstone, err := iter.MVCCValueLenAndIsTombstone()
7491+
if err != nil {
7492+
return enginepb.MVCCStats{}, errors.Wrap(err, "unable to decode MVCCValue")
74577493
}
74587494
if implicitMeta {
74597495
// INVARIANT: implicitMeta => isValue.
@@ -7463,34 +7499,21 @@ func computeStatsForIterWithVisitors(
74637499
meta.ValBytes = int64(valueLen)
74647500
meta.Deleted = mvccValueIsTombstone
74657501
meta.Timestamp.WallTime = unsafeKey.Timestamp.WallTime
7466-
}
74677502

7468-
if !isValue || implicitMeta {
74697503
metaKeySize := int64(len(unsafeKey.Key)) + 1
7470-
var metaValSize int64
7471-
if !implicitMeta {
7472-
metaValSize = int64(valueLen)
7473-
}
7474-
totalBytes := metaKeySize + metaValSize
7504+
totalBytes := metaKeySize
74757505
first = true
74767506

74777507
if isSys {
74787508
ms.SysBytes += totalBytes
74797509
ms.SysCount++
7480-
if isAbortSpanKey(unsafeKey.Key) {
7481-
ms.AbortSpanBytes += totalBytes
7510+
// We don't need to account for the abort-span key here because
7511+
// that key is not versioned.
7512+
if buildutil.CrdbTestBuild && isAbortSpanKey(unsafeKey.Key) {
7513+
return enginepb.MVCCStats{}, errors.AssertionFailedf(
7514+
"versioned abort span key encountered by ComputeStats: %s", unsafeKey.Key)
74827515
}
74837516
} else {
7484-
if !implicitMeta {
7485-
v, err := iter.UnsafeValue()
7486-
if err != nil {
7487-
return enginepb.MVCCStats{}, err
7488-
}
7489-
if err := protoutil.Unmarshal(v, &meta); err != nil {
7490-
return ms, errors.Wrap(err, "unable to decode MVCCMetadata")
7491-
}
7492-
}
7493-
74947517
if meta.Deleted {
74957518
// First value is deleted, so it's GC'able; add meta key & value bytes to age stat.
74967519
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - meta.Timestamp.WallTime/1e9)
@@ -7503,68 +7526,64 @@ func computeStatsForIterWithVisitors(
75037526
ms.LiveCount++
75047527
}
75057528
ms.KeyBytes += metaKeySize
7506-
ms.ValBytes += metaValSize
75077529
ms.KeyCount++
75087530
if meta.IsInline() {
75097531
ms.ValCount++
75107532
}
75117533
}
7512-
if !implicitMeta {
7513-
continue
7514-
}
75157534
}
75167535

75177536
totalBytes := int64(valueLen) + MVCCVersionTimestampSize
75187537
if isSys {
75197538
ms.SysBytes += totalBytes
7539+
continue
7540+
}
7541+
ms.KeyBytes += MVCCVersionTimestampSize
7542+
ms.ValBytes += int64(valueLen)
7543+
ms.ValCount++
7544+
if first {
7545+
first = false
7546+
if meta.Deleted {
7547+
// First value is deleted, so it's GC'able; add key & value bytes to age stat.
7548+
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - meta.Timestamp.WallTime/1e9)
7549+
} else if nextRangeTombstone.IsSet() {
7550+
// First value was deleted by a range tombstone; add key & value bytes to
7551+
// age stat from range tombstone onwards.
7552+
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - nextRangeTombstone.WallTime/1e9)
7553+
} else {
7554+
ms.LiveBytes += totalBytes
7555+
}
7556+
if meta.Txn != nil {
7557+
ms.IntentBytes += totalBytes
7558+
ms.IntentCount++
7559+
ms.LockCount++
7560+
ms.LockAge += nowNanos/1e9 - meta.Timestamp.WallTime/1e9
7561+
}
7562+
if meta.KeyBytes != MVCCVersionTimestampSize {
7563+
return ms, errors.Errorf("expected mvcc metadata key bytes to equal %d; got %d "+
7564+
"(meta: %s)", MVCCVersionTimestampSize, meta.KeyBytes, &meta)
7565+
}
7566+
if meta.ValBytes != int64(valueLen) {
7567+
return ms, errors.Errorf("expected mvcc metadata val bytes to equal %d; got %d "+
7568+
"(meta: %s)", valueLen, meta.ValBytes, &meta)
7569+
}
7570+
accrueGCAgeNanos = meta.Timestamp.WallTime
75207571
} else {
7521-
if first {
7522-
first = false
7523-
if meta.Deleted {
7524-
// First value is deleted, so it's GC'able; add key & value bytes to age stat.
7525-
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - meta.Timestamp.WallTime/1e9)
7526-
} else if nextRangeTombstone.IsSet() {
7527-
// First value was deleted by a range tombstone; add key & value bytes to
7528-
// age stat from range tombstone onwards.
7529-
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - nextRangeTombstone.WallTime/1e9)
7530-
} else {
7531-
ms.LiveBytes += totalBytes
7532-
}
7533-
if meta.Txn != nil {
7534-
ms.IntentBytes += totalBytes
7535-
ms.IntentCount++
7536-
ms.LockCount++
7537-
ms.LockAge += nowNanos/1e9 - meta.Timestamp.WallTime/1e9
7538-
}
7539-
if meta.KeyBytes != MVCCVersionTimestampSize {
7540-
return ms, errors.Errorf("expected mvcc metadata key bytes to equal %d; got %d "+
7541-
"(meta: %s)", MVCCVersionTimestampSize, meta.KeyBytes, &meta)
7542-
}
7543-
if meta.ValBytes != int64(valueLen) {
7544-
return ms, errors.Errorf("expected mvcc metadata val bytes to equal %d; got %d "+
7545-
"(meta: %s)", valueLen, meta.ValBytes, &meta)
7546-
}
7547-
accrueGCAgeNanos = meta.Timestamp.WallTime
7572+
// Overwritten value. Is it a deletion tombstone?
7573+
if mvccValueIsTombstone {
7574+
// The contribution of the tombstone picks up GCByteAge from its own timestamp on.
7575+
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - unsafeKey.Timestamp.WallTime/1e9)
7576+
} else if nextRangeTombstone.IsSet() && nextRangeTombstone.WallTime < accrueGCAgeNanos {
7577+
// The kv pair was deleted by a range tombstone below the next
7578+
// version, so it accumulates garbage from the range tombstone.
7579+
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - nextRangeTombstone.WallTime/1e9)
75487580
} else {
7549-
// Overwritten value. Is it a deletion tombstone?
7550-
if mvccValueIsTombstone {
7551-
// The contribution of the tombstone picks up GCByteAge from its own timestamp on.
7552-
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - unsafeKey.Timestamp.WallTime/1e9)
7553-
} else if nextRangeTombstone.IsSet() && nextRangeTombstone.WallTime < accrueGCAgeNanos {
7554-
// The kv pair was deleted by a range tombstone below the next
7555-
// version, so it accumulates garbage from the range tombstone.
7556-
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - nextRangeTombstone.WallTime/1e9)
7557-
} else {
7558-
// The kv pair is an overwritten value, so it became non-live when the closest more
7559-
// recent value was written.
7560-
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - accrueGCAgeNanos/1e9)
7561-
}
7562-
// Update for the next version we may end up looking at.
7563-
accrueGCAgeNanos = unsafeKey.Timestamp.WallTime
7581+
// The kv pair is an overwritten value, so it became non-live when the closest more
7582+
// recent value was written.
7583+
ms.GCBytesAge += totalBytes * (nowNanos/1e9 - accrueGCAgeNanos/1e9)
75647584
}
7565-
ms.KeyBytes += MVCCVersionTimestampSize
7566-
ms.ValBytes += int64(valueLen)
7567-
ms.ValCount++
7585+
// Update for the next version we may end up looking at.
7586+
accrueGCAgeNanos = unsafeKey.Timestamp.WallTime
75687587
}
75697588
}
75707589

0 commit comments

Comments
 (0)