From de2f6f979993c9c814886ee763c48b730e1997b7 Mon Sep 17 00:00:00 2001 From: sumeerbhola Date: Fri, 26 Feb 2021 13:54:54 -0500 Subject: [PATCH] storage: add a scan benchmark with resolved intents It stresses the case where many versions were written transactionally and all were resolved. This is the benchmark mentioned in https://github.com/cockroachdb/pebble/pull/1067 to justify the Pebble seek noop optimization. Release justification: Non-production code change that adds a benchmark. Release note: None --- pkg/storage/bench_test.go | 66 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/pkg/storage/bench_test.go b/pkg/storage/bench_test.go index 188df3cbacd2..aa64153d59f3 100644 --- a/pkg/storage/bench_test.go +++ b/pkg/storage/bench_test.go @@ -141,7 +141,7 @@ func BenchmarkExportToSst(b *testing.B) { const numIntentKeys = 1000 func setupKeysWithIntent( - b *testing.B, eng Engine, numVersions int, numFlushedVersions int, + b *testing.B, eng Engine, numVersions int, numFlushedVersions int, resolveAll bool, ) roachpb.LockUpdate { txnIDCount := 2 * numVersions val := []byte("value") @@ -179,7 +179,7 @@ func setupKeysWithIntent( Txn: txn.TxnMeta, Status: roachpb.COMMITTED, } - if i < numVersions { + if i < numVersions || resolveAll { batch := eng.NewBatch() for j := 0; j < numIntentKeys; j++ { key := makeKey(nil, j) @@ -198,6 +198,8 @@ func setupKeysWithIntent( return lockUpdate } +// BenchmarkIntentScan compares separated and interleaved intents, when +// reading the intent and latest version for a range of keys. func BenchmarkIntentScan(b *testing.B) { skip.UnderShort(b, "setting up unflushed data takes too long") for _, sep := range []bool{false, true} { @@ -209,7 +211,7 @@ func BenchmarkIntentScan(b *testing.B) { eng := setupMVCCInMemPebbleWithSettings( b, makeSettingsForSeparatedIntents(false, sep)) numFlushedVersions := (percentFlushed * numVersions) / 100 - setupKeysWithIntent(b, eng, numVersions, numFlushedVersions) + setupKeysWithIntent(b, eng, numVersions, numFlushedVersions, false /* resolveAll */) lower := makeKey(nil, 0) iter := eng.NewMVCCIterator(MVCCKeyAndIntentsIterKind, IterOptions{ LowerBound: lower, @@ -258,6 +260,58 @@ func BenchmarkIntentScan(b *testing.B) { } } +// BenchmarkScanAllIntentsResolved compares separated and interleaved intents, +// when reading the latest version for a range of keys, when all the intents +// have been resolved. +func BenchmarkScanAllIntentsResolved(b *testing.B) { + skip.UnderShort(b, "setting up unflushed data takes too long") + for _, sep := range []bool{false, true} { + b.Run(fmt.Sprintf("separated=%t", sep), func(b *testing.B) { + for _, numVersions := range []int{200} { + b.Run(fmt.Sprintf("versions=%d", numVersions), func(b *testing.B) { + for _, percentFlushed := range []int{0, 50, 90, 100} { + b.Run(fmt.Sprintf("percent-flushed=%d", percentFlushed), func(b *testing.B) { + eng := setupMVCCInMemPebbleWithSettings( + b, makeSettingsForSeparatedIntents(false, sep)) + numFlushedVersions := (percentFlushed * numVersions) / 100 + setupKeysWithIntent(b, eng, numVersions, numFlushedVersions, true /* resolveAll */) + lower := makeKey(nil, 0) + iter := eng.NewMVCCIterator(MVCCKeyAndIntentsIterKind, IterOptions{ + LowerBound: lower, + UpperBound: makeKey(nil, numIntentKeys), + }) + iter.SeekGE(MVCCKey{Key: lower}) + var buf []byte + b.ResetTimer() + for i := 0; i < b.N; i++ { + valid, err := iter.Valid() + if err != nil { + b.Fatal(err) + } + if !valid { + iter.SeekGE(MVCCKey{Key: lower}) + } else { + // Read latest version. + k := iter.UnsafeKey() + if !k.IsValue() { + b.Fatalf("expected value %s", k.String()) + } + // Skip to next key. + buf = append(buf[:0], k.Key...) + buf = roachpb.BytesNext(buf) + iter.SeekGE(MVCCKey{Key: buf}) + } + } + }) + } + }) + } + }) + } +} + +// BenchmarkIntentResolution compares separated and interleaved intents, when +// doing intent resolution for individual intents. func BenchmarkIntentResolution(b *testing.B) { skip.UnderShort(b, "setting up unflushed data takes too long") for _, sep := range []bool{false, true} { @@ -269,7 +323,7 @@ func BenchmarkIntentResolution(b *testing.B) { eng := setupMVCCInMemPebbleWithSettings( b, makeSettingsForSeparatedIntents(false, sep)) numFlushedVersions := (percentFlushed * numVersions) / 100 - lockUpdate := setupKeysWithIntent(b, eng, numVersions, numFlushedVersions) + lockUpdate := setupKeysWithIntent(b, eng, numVersions, numFlushedVersions, false /* resolveAll */) keys := make([]roachpb.Key, numIntentKeys) for i := range keys { keys[i] = makeKey(nil, i) @@ -298,6 +352,8 @@ func BenchmarkIntentResolution(b *testing.B) { } } +// BenchmarkIntentRangeResolution compares separated and interleaved intents, +// when doing ranged intent resolution. func BenchmarkIntentRangeResolution(b *testing.B) { skip.UnderShort(b, "setting up unflushed data takes too long") for _, sep := range []bool{false, true} { @@ -309,7 +365,7 @@ func BenchmarkIntentRangeResolution(b *testing.B) { eng := setupMVCCInMemPebbleWithSettings( b, makeSettingsForSeparatedIntents(false, sep)) numFlushedVersions := (percentFlushed * numVersions) / 100 - lockUpdate := setupKeysWithIntent(b, eng, numVersions, numFlushedVersions) + lockUpdate := setupKeysWithIntent(b, eng, numVersions, numFlushedVersions, false /* resolveAll */) keys := make([]roachpb.Key, numIntentKeys+1) for i := range keys { keys[i] = makeKey(nil, i)