Skip to content

Commit b2ccb75

Browse files
committed
backupsink: fix ooming in TestFileSSTSinkWrite
Previously, the test would allocate many 20 MiB+ buffers which sometimes oom'd the test runner. Now, the buffers allocated by the test are ~10KiB. It seems that the main reason the large buffers were required by the test is the flushes measure the compressed sst size. The test was generating long strings of zero values which compressed to almost nothing, so using correctly sized buffers would not trigger the required flushes. Release note: none Informs: #154360 Informs: #153662 Informs: #153162
1 parent 8b550fa commit b2ccb75

File tree

1 file changed

+28
-16
lines changed

1 file changed

+28
-16
lines changed

pkg/backup/backupsink/file_sst_sink_test.go

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package backupsink
88
import (
99
"context"
1010
"fmt"
11+
"math/rand"
1112
"reflect"
1213
"strconv"
1314
"strings"
@@ -122,6 +123,15 @@ func TestFileSSTSinkExtendOneFile(t *testing.T) {
122123
require.Equal(t, 1, len(progDetails.Files))
123124
}
124125

126+
func randomValue(n int64) []byte {
127+
// Create random data so that it does not compress well.
128+
b := make([]byte, n)
129+
for i := range b {
130+
b[i] = byte(rand.Int())
131+
}
132+
return b
133+
}
134+
125135
// TestFileSSTSinkWrite tests the contents of flushed files and the internal
126136
// unflushed files of the FileSSTSink under different write scenarios. Each test
127137
// writes a sequence of exportedSpans into a FileSSTSink. The test then verifies
@@ -133,6 +143,12 @@ func TestFileSSTSinkWrite(t *testing.T) {
133143
defer log.Scope(t).Close(t)
134144

135145
ctx := context.Background()
146+
testTargetFileSize := int64(10 << 10)
147+
148+
// Override the fileSpanByteLimit so we can test going over the limit without
149+
// needing large buffers that may oom the test node.
150+
defer func(oldLimit int64) { fileSpanByteLimit = oldLimit }(fileSpanByteLimit)
151+
fileSpanByteLimit = testTargetFileSize / 2
136152

137153
type testCase struct {
138154
name string
@@ -145,8 +161,7 @@ func TestFileSSTSinkWrite(t *testing.T) {
145161
//
146162
// TODO (msbutler): we currently don't test expected error handling. If this
147163
// is non-empty, we just skip the test.
148-
errorExplanation string
149-
noSSTSizeOverride bool
164+
errorExplanation string
150165
}
151166

152167
for _, tt := range []testCase{{name: "out-of-order-key-boundary",
@@ -278,7 +293,7 @@ func TestFileSSTSinkWrite(t *testing.T) {
278293
{
279294
name: "size-flush",
280295
exportSpans: []ExportedSpan{
281-
newExportedSpanBuilder("a", "c").withKVs([]kvAndTS{{key: "a", timestamp: 10, value: make([]byte, 20<<20)}, {key: "b", timestamp: 10}}).build(),
296+
newExportedSpanBuilder("a", "c").withKVs([]kvAndTS{{key: "a", timestamp: 10, value: randomValue(testTargetFileSize)}, {key: "b", timestamp: 10}}).build(),
282297
newExportedSpanBuilder("d", "f").withKVs([]kvAndTS{{key: "d", timestamp: 10}, {key: "e", timestamp: 10}}).build(),
283298
},
284299
flushedSpans: []roachpb.Spans{
@@ -292,7 +307,7 @@ func TestFileSSTSinkWrite(t *testing.T) {
292307
// No flush can occur between two versions of the same key. Further, we must combine flushes which split a row.
293308
name: "no-size-flush-if-mid-mvcc",
294309
exportSpans: []ExportedSpan{
295-
newRawExportedSpanBuilder(s2k0("a"), s2k0("c"), s2k0("c")).withKVs([]kvAndTS{{key: "a", timestamp: 10, value: make([]byte, 20<<20)}, {key: "c", timestamp: 10}}).build(),
310+
newRawExportedSpanBuilder(s2k0("a"), s2k0("c"), s2k0("c")).withKVs([]kvAndTS{{key: "a", timestamp: 10, value: randomValue(testTargetFileSize)}, {key: "c", timestamp: 10}}).build(),
296311
newRawExportedSpanBuilder(s2k0("c"), s2k0("f"), s2k0("f")).withKVs([]kvAndTS{{key: "c", timestamp: 8}, {key: "f", timestamp: 10}}).build(),
297312
},
298313
flushedSpans: []roachpb.Spans{},
@@ -305,9 +320,9 @@ func TestFileSSTSinkWrite(t *testing.T) {
305320
name: "no-size-flush-mid-col-family",
306321
exportSpans: []ExportedSpan{
307322
newRawExportedSpanBuilder(s2kWithColFamily("c", 0), s2kWithColFamily("c", 1), s2kWithColFamily("c", 1)).withKVs([]kvAndTS{
308-
{key: "c", timestamp: 10, value: make([]byte, 20<<20)}}).build(),
323+
{key: "c", timestamp: 10, value: randomValue(testTargetFileSize)}}).build(),
309324
newRawExportedSpanBuilder(s2kWithColFamily("c", 1), s2kWithColFamily("c", 2), s2kWithColFamily("c", 2)).withKVs([]kvAndTS{
310-
{key: "c", timestamp: 10, value: make([]byte, 20<<20)}}).buildWithEncoding(func(stingedKey string) roachpb.Key { return s2kWithColFamily(stingedKey, 1) }),
325+
{key: "c", timestamp: 10, value: randomValue(testTargetFileSize)}}).buildWithEncoding(func(stingedKey string) roachpb.Key { return s2kWithColFamily(stingedKey, 1) }),
311326
},
312327
flushedSpans: []roachpb.Spans{},
313328
unflushedSpans: []roachpb.Spans{
@@ -318,7 +333,7 @@ func TestFileSSTSinkWrite(t *testing.T) {
318333
// It's safe to flush at the range boundary.
319334
name: "size-flush-at-range-boundary",
320335
exportSpans: []ExportedSpan{
321-
newRawExportedSpanBuilder(s2k("a"), s2k("d"), s2k("d")).withKVs([]kvAndTS{{key: "a", timestamp: 10, value: make([]byte, 20<<20)}, {key: "c", timestamp: 10}}).build(),
336+
newRawExportedSpanBuilder(s2k("a"), s2k("d"), s2k("d")).withKVs([]kvAndTS{{key: "a", timestamp: 10, value: randomValue(testTargetFileSize)}, {key: "c", timestamp: 10}}).build(),
322337
},
323338
flushedSpans: []roachpb.Spans{
324339
{{Key: s2k("a"), EndKey: s2k("d")}},
@@ -332,7 +347,7 @@ func TestFileSSTSinkWrite(t *testing.T) {
332347
// row between two column families.
333348
name: "trim-resume-key",
334349
exportSpans: []ExportedSpan{
335-
newRawExportedSpanBuilder(s2k0("a"), s2k0("c"), s2k("c")).withKVs([]kvAndTS{{key: "a", timestamp: 10, value: make([]byte, 20<<20)}}).build(),
350+
newRawExportedSpanBuilder(s2k0("a"), s2k0("c"), s2k("c")).withKVs([]kvAndTS{{key: "a", timestamp: 10, value: randomValue(testTargetFileSize)}}).build(),
336351
},
337352
flushedSpans: []roachpb.Spans{
338353
{{Key: s2k0("a"), EndKey: s2k("c")}},
@@ -344,24 +359,23 @@ func TestFileSSTSinkWrite(t *testing.T) {
344359
// even if the next span's start key matches the file's end key.
345360
name: "file-size-cut",
346361
exportSpans: []ExportedSpan{
347-
newExportedSpanBuilder("a", "c").withKVs([]kvAndTS{{key: "a", timestamp: 10, value: make([]byte, 64<<20)}, {key: "b", timestamp: 10}}).build(),
362+
newExportedSpanBuilder("a", "c").withKVs([]kvAndTS{{key: "a", timestamp: 10, value: randomValue(fileSpanByteLimit)}, {key: "b", timestamp: 10}}).build(),
348363
newExportedSpanBuilder("c", "f").withKVs([]kvAndTS{{key: "c", timestamp: 10}, {key: "e", timestamp: 10}}).build(),
349364
},
350365
flushedSpans: []roachpb.Spans{},
351366
unflushedSpans: []roachpb.Spans{
352367
{{Key: s2k0("a"), EndKey: s2k0("c")}, {Key: s2k0("c"), EndKey: s2k0("f")}},
353368
},
354-
noSSTSizeOverride: true,
355369
},
356370
{
357371
// No file cut can occur between the two column families of the same row,
358372
// even if the file is sufficiently large to get cut.
359373
name: "no-file-cut-mid-col-family",
360374
exportSpans: []ExportedSpan{
361375
newRawExportedSpanBuilder(s2kWithColFamily("c", 0), s2kWithColFamily("c", 1), s2kWithColFamily("c", 1)).withKVs([]kvAndTS{
362-
{key: "c", timestamp: 10, value: make([]byte, 65<<20)}}).build(),
376+
{key: "c", timestamp: 10, value: randomValue(testTargetFileSize)}}).build(),
363377
newRawExportedSpanBuilder(s2kWithColFamily("c", 1), s2kWithColFamily("c", 2), s2kWithColFamily("c", 2)).withKVs([]kvAndTS{
364-
{key: "c", timestamp: 10, value: make([]byte, 20<<20)}}).buildWithEncoding(func(stingedKey string) roachpb.Key { return s2kWithColFamily(stingedKey, 1) }),
378+
{key: "c", timestamp: 10, value: randomValue(testTargetFileSize / 2)}}).buildWithEncoding(func(stingedKey string) roachpb.Key { return s2kWithColFamily(stingedKey, 1) }),
365379
},
366380
flushedSpans: []roachpb.Spans{},
367381
unflushedSpans: []roachpb.Spans{
@@ -377,9 +391,7 @@ func TestFileSSTSinkWrite(t *testing.T) {
377391
return
378392
}
379393
st := cluster.MakeTestingClusterSettings()
380-
if !tt.noSSTSizeOverride {
381-
targetFileSize.Override(ctx, &st.SV, 10<<10)
382-
}
394+
targetFileSize.Override(ctx, &st.SV, testTargetFileSize)
383395

384396
sink, store := fileSSTSinkTestSetup(t, st, elide)
385397
defer func() {
@@ -534,7 +546,7 @@ func TestFileSSTSinkStats(t *testing.T) {
534546
sinkStats{hlc.Timestamp{WallTime: 10}, 3, 3, 0, 0, 0, 1}},
535547
{
536548
// Write an exported span that comes after all spans so far. This span has enough data for a size flush.
537-
newExportedSpanBuilder("g", "h").withKVs([]kvAndTS{{key: "g", timestamp: 10, value: make([]byte, 20<<20)}}).build(),
549+
newExportedSpanBuilder("g", "h").withKVs([]kvAndTS{{key: "g", timestamp: 10, value: randomValue(10 << 10)}}).build(),
538550
sinkStats{hlc.Timestamp{WallTime: 0}, 0, 4, 1, 0, 1, 1}},
539551
{
540552
// Write the first exported span after the flush.

0 commit comments

Comments
 (0)