Skip to content

Commit 6ee797c

Browse files
committed
db: add MinimumLatencyTolerantSize to ValueSeparationPolicy struct
This patch adds a globally configurable MinimumLatencyTolerant size to the ValueSeparationPolicy struct. Informs: #5377
1 parent 12893cb commit 6ee797c

File tree

10 files changed

+74
-49
lines changed

10 files changed

+74
-49
lines changed

data_test.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,6 +1672,7 @@ func describeLSM(d *DB, verbose bool) string {
16721672

16731673
func parseDBOptionsArgs(opts *Options, args []datadriven.CmdArg) error {
16741674
var spanPolicies []SpanAndPolicy
1675+
var policy ValueSeparationPolicy
16751676
for _, cmdArg := range args {
16761677
switch cmdArg.Key {
16771678
case "auto-compactions":
@@ -1801,10 +1802,13 @@ func parseDBOptionsArgs(opts *Options, args []datadriven.CmdArg) error {
18011802
Start: []byte(cmdArg.Vals[0]),
18021803
End: []byte(cmdArg.Vals[1]),
18031804
}
1804-
policy := SpanPolicy{ValueStoragePolicy: ValueStorageLatencyTolerant}
1805+
policyAdjustment := ValueStoragePolicyAdjustment{
1806+
OverrideBlobSeparationMinimumSize: policy.MinimumLatencyTolerantSize,
1807+
}
1808+
spanPolicy := SpanPolicy{ValueStoragePolicy: policyAdjustment}
18051809
spanPolicies = append(spanPolicies, SpanAndPolicy{
18061810
KeyRange: span,
1807-
Policy: policy,
1811+
Policy: spanPolicy,
18081812
})
18091813
case "target-file-sizes":
18101814
if len(cmdArg.Vals) > len(opts.Levels) {
@@ -1831,7 +1835,6 @@ func parseDBOptionsArgs(opts *Options, args []datadriven.CmdArg) error {
18311835
opts.FlushSplitBytes = flushSplitBytes
18321836

18331837
case "value-separation":
1834-
var policy ValueSeparationPolicy
18351838
if len(cmdArg.Vals) == 1 && cmdArg.Vals[0] == "off" || cmdArg.Vals[0] == "disabled" {
18361839
policy.Enabled = false
18371840
} else {
@@ -1843,6 +1846,7 @@ func parseDBOptionsArgs(opts *Options, args []datadriven.CmdArg) error {
18431846
name = arg[:i]
18441847
value = arg[i+1:]
18451848
}
1849+
policy.MinimumLatencyTolerantSize = 10
18461850
var err error
18471851
switch name {
18481852
case "enabled", "disabled":
@@ -1852,6 +1856,11 @@ func parseDBOptionsArgs(opts *Options, args []datadriven.CmdArg) error {
18521856
if err != nil {
18531857
return err
18541858
}
1859+
case "min-latency-tolerant-size":
1860+
policy.MinimumLatencyTolerantSize, err = strconv.Atoi(value)
1861+
if err != nil {
1862+
return err
1863+
}
18551864
case "max-ref-depth":
18561865
policy.MaxBlobReferenceDepth, err = strconv.Atoi(value)
18571866
if err != nil {

event_listener_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -633,9 +633,10 @@ func TestBlobCorruptionEvent(t *testing.T) {
633633
}
634634
opts.Experimental.ValueSeparationPolicy = func() ValueSeparationPolicy {
635635
return ValueSeparationPolicy{
636-
Enabled: true,
637-
MinimumSize: 1,
638-
MaxBlobReferenceDepth: 10,
636+
Enabled: true,
637+
MinimumSize: 1,
638+
MinimumLatencyTolerantSize: 10,
639+
MaxBlobReferenceDepth: 10,
639640
}
640641
}
641642
d, err := Open("", opts)

iterator_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,9 +1420,10 @@ func TestIteratorValueRetrievalProfile(t *testing.T) {
14201420
opts.FormatMajorVersion = internalFormatNewest
14211421
opts.Experimental.ValueSeparationPolicy = func() ValueSeparationPolicy {
14221422
return ValueSeparationPolicy{
1423-
Enabled: true,
1424-
MinimumSize: 1,
1425-
MaxBlobReferenceDepth: 5,
1423+
Enabled: true,
1424+
MinimumSize: 1,
1425+
MinimumLatencyTolerantSize: 10,
1426+
MaxBlobReferenceDepth: 5,
14261427
}
14271428
}
14281429
d := newTestkeysDatabase(t, opts, testkeys.Alpha(2), rand.New(rand.NewPCG(1, 1)))

metamorphic/options.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,13 @@ func defaultOptions(kf KeyFormat) *pebble.Options {
311311

312312
opts.Experimental.ValueSeparationPolicy = func() pebble.ValueSeparationPolicy {
313313
return pebble.ValueSeparationPolicy{
314-
Enabled: true,
315-
MinimumSize: 5,
316-
MaxBlobReferenceDepth: 3,
317-
RewriteMinimumAge: 50 * time.Millisecond,
318-
GarbageRatioLowPriority: 0.10, // 10% garbage
319-
GarbageRatioHighPriority: 0.30, // 30% garbage
314+
Enabled: true,
315+
MinimumSize: 5,
316+
MinimumLatencyTolerantSize: 10,
317+
MaxBlobReferenceDepth: 3,
318+
RewriteMinimumAge: 50 * time.Millisecond,
319+
GarbageRatioLowPriority: 0.10, // 10% garbage
320+
GarbageRatioHighPriority: 0.30, // 30% garbage
320321
}
321322
}
322323

@@ -896,12 +897,13 @@ func RandomOptions(rng *rand.Rand, kf KeyFormat, cfg RandomOptionsCfg) *TestOpti
896897
}
897898
lowPri := max(rng.Float64(), 0.05)
898899
policy := pebble.ValueSeparationPolicy{
899-
Enabled: true,
900-
MinimumSize: 1 + rng.IntN(maxValueSize),
901-
MaxBlobReferenceDepth: 2 + rng.IntN(9), // 2-10
902-
RewriteMinimumAge: time.Duration(rng.IntN(90)+10) * time.Millisecond, // [10ms, 100ms)
903-
GarbageRatioLowPriority: lowPri,
904-
GarbageRatioHighPriority: lowPri + rand.Float64()*(1.0-lowPri), // [lowPri, 1.0)
900+
Enabled: true,
901+
MinimumSize: 1 + rng.IntN(maxValueSize),
902+
MinimumLatencyTolerantSize: 5 + rng.IntN(11), // [5, 15] bytes
903+
MaxBlobReferenceDepth: 2 + rng.IntN(9), // 2-10
904+
RewriteMinimumAge: time.Duration(rng.IntN(90)+10) * time.Millisecond, // [10ms, 100ms)
905+
GarbageRatioLowPriority: lowPri,
906+
GarbageRatioHighPriority: lowPri + rand.Float64()*(1.0-lowPri), // [lowPri, 1.0)
905907
}
906908
opts.Experimental.ValueSeparationPolicy = func() pebble.ValueSeparationPolicy {
907909
return policy

metrics_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,10 @@ func TestMetrics(t *testing.T) {
269269
opts.Experimental.EnableValueBlocks = func() bool { return true }
270270
opts.Experimental.ValueSeparationPolicy = func() ValueSeparationPolicy {
271271
return ValueSeparationPolicy{
272-
Enabled: true,
273-
MinimumSize: 3,
274-
MaxBlobReferenceDepth: 5,
272+
Enabled: true,
273+
MinimumSize: 3,
274+
MinimumLatencyTolerantSize: 10,
275+
MaxBlobReferenceDepth: 5,
275276
}
276277
}
277278
opts.TargetFileSizes[0] = 50

options.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,12 @@ type ValueSeparationPolicy struct {
12331233
//
12341234
// MinimumSize must be > 0.
12351235
MinimumSize int
1236+
// MinimumLatencyTolerantSize specifies the minimum size of a value that can
1237+
// be separated into a blob file if said value is a part of a latency tolerant
1238+
// span.
1239+
//
1240+
// MinimumLatencyTolerantSize must be > 0.
1241+
MinimumLatencyTolerantSize int
12361242
// MaxBlobReferenceDepth limits the number of potentially overlapping (in
12371243
// the keyspace) blob files that can be referenced by a single sstable. If a
12381244
// compaction may produce an output sstable referencing more than this many
@@ -1274,8 +1280,7 @@ type ValueSeparationPolicy struct {
12741280
GarbageRatioHighPriority float64
12751281
}
12761282

1277-
// SpanPolicy contains policies that can vary by key range. The zero value is
1278-
// the default value.
1283+
// SpanPolicy contains policies that can vary by key range.
12791284
type SpanPolicy struct {
12801285
// Prefer a faster compression algorithm for the keys in this span.
12811286
//
@@ -1342,13 +1347,6 @@ func (vsp *ValueStoragePolicyAdjustment) ContainsOverrides() bool {
13421347
return vsp.OverrideBlobSeparationMinimumSize > 0 || vsp.DisableSeparationBySuffix
13431348
}
13441349

1345-
// ValueStorageLatencyTolerant is the suggested ValueStoragePolicyAdjustment
1346-
// to use for key ranges that can tolerate higher value retrieval
1347-
// latency.
1348-
var ValueStorageLatencyTolerant = ValueStoragePolicyAdjustment{
1349-
OverrideBlobSeparationMinimumSize: 10,
1350-
}
1351-
13521350
// ValueStorageLowReadLatency is the suggested ValueStoragePolicyAdjustment
13531351
// to use for key ranges that require low value retrieval latency.
13541352
var ValueStorageLowReadLatency = ValueStoragePolicyAdjustment{
@@ -1858,6 +1856,7 @@ func (o *Options) String() string {
18581856
fmt.Fprintln(&buf, "[Value Separation]")
18591857
fmt.Fprintf(&buf, " enabled=%t\n", policy.Enabled)
18601858
fmt.Fprintf(&buf, " minimum_size=%d\n", policy.MinimumSize)
1859+
fmt.Fprintf(&buf, " minimum_latency_tolerant_size=%d\n", policy.MinimumLatencyTolerantSize)
18611860
fmt.Fprintf(&buf, " max_blob_reference_depth=%d\n", policy.MaxBlobReferenceDepth)
18621861
fmt.Fprintf(&buf, " rewrite_minimum_age=%s\n", policy.RewriteMinimumAge)
18631862
fmt.Fprintf(&buf, " garbage_ratio_low_priority=%.2f\n", policy.GarbageRatioLowPriority)
@@ -2308,6 +2307,10 @@ func (o *Options) Parse(s string, hooks *ParseHooks) error {
23082307
var minimumSize int
23092308
minimumSize, err = strconv.Atoi(value)
23102309
valSepPolicy.MinimumSize = minimumSize
2310+
case "minimum_latency_tolerant_size":
2311+
var minimumLatencyTolerantSize int
2312+
minimumLatencyTolerantSize, err = strconv.Atoi(value)
2313+
valSepPolicy.MinimumLatencyTolerantSize = minimumLatencyTolerantSize
23112314
case "max_blob_reference_depth":
23122315
valSepPolicy.MaxBlobReferenceDepth, err = strconv.Atoi(value)
23132316
case "rewrite_minimum_age":
@@ -2608,6 +2611,9 @@ func (o *Options) Validate() error {
26082611
if policy.MinimumSize <= 0 {
26092612
fmt.Fprintf(&buf, "ValueSeparationPolicy.MinimumSize (%d) must be > 0\n", policy.MinimumSize)
26102613
}
2614+
if policy.MinimumLatencyTolerantSize <= 0 {
2615+
fmt.Fprintf(&buf, "ValueSeparationPolicy.MinimumLatencyTolerantSize (%d) must be > 0\n", policy.MinimumLatencyTolerantSize)
2616+
}
26112617
if policy.MaxBlobReferenceDepth <= 0 {
26122618
fmt.Fprintf(&buf, "ValueSeparationPolicy.MaxBlobReferenceDepth (%d) must be > 0\n", policy.MaxBlobReferenceDepth)
26132619
}

options_test.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ func (o *Options) randomizeForTesting(t testing.TB) {
4242
if o.FormatMajorVersion >= FormatValueSeparation && o.Experimental.ValueSeparationPolicy == nil && rand.Int64N(4) > 0 {
4343
lowPri := 0.1 + rand.Float64()*0.9 // [0.1, 1.0)
4444
policy := ValueSeparationPolicy{
45-
Enabled: true,
46-
MinimumSize: 1 << rand.IntN(10), // [1, 512]
47-
MaxBlobReferenceDepth: rand.IntN(10) + 1, // [1, 10)
45+
Enabled: true,
46+
MinimumSize: 1 << rand.IntN(10), // [1, 512]
47+
MinimumLatencyTolerantSize: 5 + rand.IntN(11), // [5, 15]
48+
MaxBlobReferenceDepth: 1 + rand.IntN(10), // [1, 10]
4849
// Constrain the rewrite minimum age to [0, 15s).
4950
RewriteMinimumAge: time.Duration(rand.IntN(15)) * time.Second,
5051
GarbageRatioLowPriority: lowPri,
@@ -658,7 +659,9 @@ func TestStaticSpanPolicyFunc(t *testing.T) {
658659
case "lowlatency":
659660
sap.Policy.ValueStoragePolicy = ValueStorageLowReadLatency
660661
case "latencytolerant":
661-
sap.Policy.ValueStoragePolicy = ValueStorageLatencyTolerant
662+
sap.Policy.ValueStoragePolicy = ValueStoragePolicyAdjustment{
663+
OverrideBlobSeparationMinimumSize: 10,
664+
}
662665
default:
663666
t.Fatalf("unknown policy: %s", tok)
664667
}

replay/replay_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,11 @@ func collectCorpus(t *testing.T, fs *vfs.MemFS, name string) {
350350
}
351351
opts.Experimental.ValueSeparationPolicy = func() pebble.ValueSeparationPolicy {
352352
return pebble.ValueSeparationPolicy{
353-
Enabled: true,
354-
MinimumSize: 3,
355-
MaxBlobReferenceDepth: 5,
356-
RewriteMinimumAge: 15 * time.Minute,
353+
Enabled: true,
354+
MinimumSize: 3,
355+
MinimumLatencyTolerantSize: 10,
356+
MaxBlobReferenceDepth: 5,
357+
RewriteMinimumAge: 15 * time.Minute,
357358
}
358359
}
359360
setDefaultExperimentalOpts(opts)

replay/testdata/replay_val_sep

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ tree
1717
0 LOCK
1818
152 MANIFEST-000010
1919
250 MANIFEST-000013
20-
2911 OPTIONS-000002
20+
2946 OPTIONS-000002
2121
0 marker.format-version.000011.024
2222
0 marker.manifest.000003.MANIFEST-000013
2323
simple_val_sep/
@@ -32,7 +32,7 @@ tree
3232
11 000011.log
3333
687 000012.sst
3434
187 MANIFEST-000013
35-
2911 OPTIONS-000002
35+
2946 OPTIONS-000002
3636
0 marker.format-version.000001.024
3737
0 marker.manifest.000001.MANIFEST-000013
3838

@@ -92,6 +92,7 @@ cat build/OPTIONS-000002
9292
[Value Separation]
9393
enabled=true
9494
minimum_size=3
95+
minimum_latency_tolerant_size=10
9596
max_blob_reference_depth=5
9697
rewrite_minimum_age=15m0s
9798
garbage_ratio_low_priority=0.00

testdata/metrics

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ Iter category stats:
236236

237237
disk-usage
238238
----
239-
3,653B
239+
3,688B
240240

241241
batch
242242
set b 2
@@ -365,7 +365,7 @@ Iter category stats:
365365

366366
disk-usage
367367
----
368-
5,886B
368+
5,921B
369369

370370
# Closing iter a will release one of the zombie memtables.
371371

@@ -584,7 +584,7 @@ Iter category stats:
584584

585585
disk-usage
586586
----
587-
5,199B
587+
5,234B
588588

589589
# Closing iter b will release the last zombie sstable and the last zombie memtable.
590590

@@ -695,7 +695,7 @@ Iter category stats:
695695

696696
disk-usage
697697
----
698-
4,512B
698+
4,547B
699699

700700
additional-metrics
701701
----
@@ -2600,12 +2600,12 @@ Blob files:
26002600

26012601
disk-usage
26022602
----
2603-
7,574B
2603+
7,609B
26042604

26052605
init reopen
26062606
----
26072607

26082608
# The disk usage is expected to go down a bit because we remove the WALs.
26092609
disk-usage
26102610
----
2611-
7,057B
2611+
7,092B

0 commit comments

Comments
 (0)