Skip to content

Commit

Permalink
sstable: add jemalloc size classes to tests
Browse files Browse the repository at this point in the history
We add some tests with the jemalloc size classes and add them to the
metamorphic test as well. We will update the crdb code to use
`pebble.JemallocSizeClasses`.
  • Loading branch information
RaduBerinde committed Oct 17, 2024
1 parent b07f0b2 commit c6b097e
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 4 deletions.
18 changes: 17 additions & 1 deletion metamorphic/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ func parseOptions(
case "TestOptions.use_excise":
opts.useExcise = true
return true
case "TestOptions.use_jemalloc_size_classes":
opts.Opts.AllocatorSizeClasses = pebble.JemallocSizeClasses
return true
default:
if customOptionParsers == nil {
return false
Expand Down Expand Up @@ -256,6 +259,12 @@ func optionsToString(opts *TestOptions) string {
if opts.useExcise {
fmt.Fprintf(&buf, " use_excise=%v\n", opts.useExcise)
}
if opts.Opts.AllocatorSizeClasses != nil {
if fmt.Sprint(opts.Opts.AllocatorSizeClasses) != fmt.Sprint(pebble.JemallocSizeClasses) {
panic(fmt.Sprintf("unexpected AllocatorSizeClasses %v", opts.Opts.AllocatorSizeClasses))
}
fmt.Fprint(&buf, " use_jemalloc_size_classes=true\n")
}
for _, customOpt := range opts.CustomOpts {
fmt.Fprintf(&buf, " %s=%s\n", customOpt.Name(), customOpt.Value())
}
Expand Down Expand Up @@ -445,6 +454,8 @@ func standardOptions() []*TestOptions {
2: `
[Options]
disable_wal=true
[TestOptions]
use_jemalloc_size_classes=true
`,
3: `
[Options]
Expand Down Expand Up @@ -524,7 +535,8 @@ func standardOptions() []*TestOptions {
`,
21: `
[TestOptions]
use_disk=true
use_disk=true
use_jemalloc_size_classes=true
`,
22: `
[Options]
Expand All @@ -542,6 +554,7 @@ func standardOptions() []*TestOptions {
25: `
[TestOptions]
enable_value_blocks=true
use_jemalloc_size_classes=true
`,
26: fmt.Sprintf(`
[Options]
Expand Down Expand Up @@ -705,6 +718,9 @@ func RandomOptions(
AllowL0: rng.IntN(4) == 1, // 25% of the time
}
}
if rng.IntN(2) == 0 {
opts.AllocatorSizeClasses = pebble.JemallocSizeClasses
}

var lopts pebble.LevelOptions
lopts.BlockRestartInterval = 1 + rng.IntN(64) // 1 - 64
Expand Down
3 changes: 3 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,9 @@ type WALFailoverOptions struct {
// ReadaheadConfig controls the use of read-ahead.
type ReadaheadConfig = objstorageprovider.ReadaheadConfig

// JemallocSizeClasses exports sstable.JemallocSizeClasses.
var JemallocSizeClasses = sstable.JemallocSizeClasses

// DebugCheckLevels calls CheckLevels on the provided database.
// It may be set in the DebugCheck field of Options to check
// level invariants whenever a new version is installed.
Expand Down
11 changes: 8 additions & 3 deletions sstable/block/flush_governor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@
// of this source code is governed by a BSD-style license that can be found in
// the LICENSE file.

package block
package block_test

import (
"testing"

"github.com/cockroachdb/datadriven"
"github.com/cockroachdb/pebble/sstable"
"github.com/cockroachdb/pebble/sstable/block"
)

func TestFlushGovernor(t *testing.T) {
var fg FlushGovernor
var fg block.FlushGovernor
datadriven.RunTest(t, "testdata/flush_governor", func(t *testing.T, td *datadriven.TestData) string {
switch td.Cmd {
case "init":
Expand All @@ -23,7 +25,10 @@ func TestFlushGovernor(t *testing.T) {
td.MaybeScanArgs(t, "threshold", &blockSizeThreshold)
td.MaybeScanArgs(t, "size-class-aware-threshold", &sizeClassAwareThreshold)
td.MaybeScanArgs(t, "size-classes", &classes)
fg = MakeFlushGovernor(targetBlockSize, blockSizeThreshold, sizeClassAwareThreshold, classes)
if td.HasArg("jemalloc-size-classes") {
classes = sstable.JemallocSizeClasses
}
fg = block.MakeFlushGovernor(targetBlockSize, blockSizeThreshold, sizeClassAwareThreshold, classes)
return fg.String()

case "should-flush":
Expand Down
23 changes: 23 additions & 0 deletions sstable/block/testdata/flush_governor
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,26 @@ init target-block-size=1000 size-class-aware-threshold=60 size-classes=(500, 600
low watermark: 600
high watermark: 1018
boundaries: [818 868 918 968]

# Test with jemalloc boundaries.
init target-block-size=32768 jemalloc-size-classes
----
low watermark: 19661
high watermark: 40928
boundaries: [20448 24544 28640 32736]

# We should flush to avoid exceeding the boundary.
should-flush size-before=32000 size-after=32766
----
should flush

# We should not flush since we waste less space against the 40KiB boundary.
should-flush size-before=30000 size-after=39000
----
should not flush

# We should flush even if we would waste less space against the 48KiB boundary
# (it's not the first boundary after the target size).
should-flush size-before=39000 size-after=48500
----
should flush
17 changes: 17 additions & 0 deletions sstable/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,23 @@ type WriterOptions struct {
disableObsoleteCollector bool
}

// JemallocSizeClasses are a subset of available size classes in jemalloc[1],
// suitable for the AllocatorSizeClasses option.
//
// The size classes are used when writing sstables for determining target block
// sizes for flushes, with the goal of reducing internal memory fragmentation
// when the blocks are later loaded into the block cache. We only use the size
// classes between 16KiB - 256KiB as block limits fall in that range.
//
// [1] https://jemalloc.net/jemalloc.3.html#size_classes
var JemallocSizeClasses = []int{
16 * 1024,
20 * 1024, 24 * 1024, 28 * 1024, 32 * 1024, // 4KiB spacing
40 * 1024, 48 * 1024, 56 * 1024, 64 * 1024, // 8KiB spacing
80 * 1024, 96 * 1024, 112 * 1024, 128 * 1024, // 16KiB spacing.
160 * 1024, 192 * 1024, 224 * 1024, 256 * 1024, // 32KiB spacing.
}

// SetInternal sets the internal writer options. Note that even though this
// method is public, a caller outside the pebble package can't construct a value
// to pass to it.
Expand Down

0 comments on commit c6b097e

Please sign in to comment.