Skip to content

Commit

Permalink
record: pool LogWriter blocks
Browse files Browse the repository at this point in the history
When a LogWriter is closed, return its blocks to a sync.Pool for reuse by a
subsequent LogWriter to reduce allocations.

```
goos: darwin
goarch: arm64
pkg: github.com/cockroachdb/pebble/record
                                    │   old.txt    │               new.txt               │
                                    │    sec/op    │   sec/op     vs base                │
QueueWALBlocks/record-size=64B-10      32.80m ± 2%   28.23m ± 2%  -13.93% (p=0.000 n=10)
QueueWALBlocks/record-size=512B-10     15.12m ± 2%   11.55m ± 1%  -23.58% (p=0.000 n=10)
QueueWALBlocks/record-size=1.0KB-10    14.23m ± 4%   10.93m ± 4%  -23.20% (p=0.000 n=10)
QueueWALBlocks/record-size=2.0KB-10    13.84m ± 2%   10.52m ± 2%  -24.00% (p=0.000 n=10)
QueueWALBlocks/record-size=32KB-10    13.197m ± 1%   9.784m ± 2%  -25.87% (p=0.000 n=10)
geomean                                16.67m        12.97m       -22.22%

                                    │   old.txt    │               new.txt                │
                                    │     B/s      │     B/s       vs base                │
QueueWALBlocks/record-size=64B-10     1.906Gi ± 2%   2.214Gi ± 2%  +16.18% (p=0.000 n=10)
QueueWALBlocks/record-size=512B-10    4.134Gi ± 2%   5.411Gi ± 1%  +30.86% (p=0.000 n=10)
QueueWALBlocks/record-size=1.0KB-10   4.393Gi ± 4%   5.721Gi ± 4%  +30.21% (p=0.000 n=10)
QueueWALBlocks/record-size=2.0KB-10   4.514Gi ± 2%   5.940Gi ± 2%  +31.58% (p=0.000 n=10)
QueueWALBlocks/record-size=32KB-10    4.736Gi ± 1%   6.388Gi ± 2%  +34.89% (p=0.000 n=10)
geomean                               3.748Gi        4.820Gi       +28.58%

                                    │     old.txt     │               new.txt                │
                                    │      B/op       │     B/op      vs base                │
QueueWALBlocks/record-size=64B-10     96058.79Ki ± 0%   99.72Ki ± 1%  -99.90% (p=0.000 n=10)
QueueWALBlocks/record-size=512B-10    83738.81Ki ± 0%   98.77Ki ± 0%  -99.88% (p=0.000 n=10)
QueueWALBlocks/record-size=1.0KB-10   82858.79Ki ± 0%   98.99Ki ± 0%  -99.88% (p=0.000 n=10)
QueueWALBlocks/record-size=2.0KB-10   82418.81Ki ± 0%   98.78Ki ± 0%  -99.88% (p=0.000 n=10)
QueueWALBlocks/record-size=32KB-10    82019.15Ki ± 0%   99.02Ki ± 0%  -99.88% (p=0.000 n=10)
geomean                                  83.26Mi        99.06Ki       -99.88%

                                    │   old.txt    │              new.txt               │
                                    │  allocs/op   │ allocs/op   vs base                │
QueueWALBlocks/record-size=64B-10     2413.00 ± 0%   14.00 ± 0%  -99.42% (p=0.000 n=10)
QueueWALBlocks/record-size=512B-10    2105.00 ± 0%   14.00 ± 0%  -99.33% (p=0.000 n=10)
QueueWALBlocks/record-size=1.0KB-10   2083.00 ± 0%   14.00 ± 7%  -99.33% (p=0.000 n=10)
QueueWALBlocks/record-size=2.0KB-10   2072.00 ± 0%   14.00 ± 0%  -99.32% (p=0.000 n=10)
QueueWALBlocks/record-size=32KB-10    2062.00 ± 0%   14.00 ± 7%  -99.32% (p=0.000 n=10)
geomean                                2.143k        14.00       -99.35%
```
  • Loading branch information
jbowens committed Jul 24, 2023
1 parent f79908f commit 2e84c30
Showing 1 changed file with 17 additions and 2 deletions.
19 changes: 17 additions & 2 deletions record/log_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,13 @@ type LogWriterConfig struct {
// than this threshold allows.
const initialAllocatedBlocksCap = 32

// blockPool pools *blocks to avoid allocations. Blocks are only added to the
// Pool when a LogWriter is closed. Before that, free blocks are maintained
// within a LogWriter's own internal free list `w.free.blocks`.
var blockPool = sync.Pool{
New: func() any { return &block{} },
}

// NewLogWriter returns a new LogWriter.
func NewLogWriter(w io.Writer, logNum base.FileNum, logWriterConfig LogWriterConfig) *LogWriter {
c, _ := w.(io.Closer)
Expand All @@ -334,7 +341,7 @@ func NewLogWriter(w io.Writer, logNum base.FileNum, logWriterConfig LogWriterCon
queueSemChan: logWriterConfig.QueueSemChan,
}
r.free.blocks = make([]*block, 0, initialAllocatedBlocksCap)
r.block = &block{}
r.block = blockPool.Get().(*block)
r.flusher.ready.init(&r.flusher.Mutex, &r.flusher.syncQ)
r.flusher.closed = make(chan struct{})
r.flusher.pending = make([]*block, 0, cap(r.free.blocks))
Expand Down Expand Up @@ -566,7 +573,7 @@ func (w *LogWriter) queueBlock() {
// because w.block is protected by w.flusher.Mutex.
w.free.Lock()
if len(w.free.blocks) == 0 {
w.free.blocks = append(w.free.blocks, &block{})
w.free.blocks = append(w.free.blocks, blockPool.Get().(*block))
}
nextBlock := w.free.blocks[len(w.free.blocks)-1]
w.free.blocks = w.free.blocks[:len(w.free.blocks)-1]
Expand Down Expand Up @@ -615,6 +622,7 @@ func (w *LogWriter) Close() error {
if f.fsyncLatency != nil {
f.fsyncLatency.Observe(float64(syncLatency))
}
free := w.free.blocks
f.Unlock()

if w.c != nil {
Expand All @@ -624,6 +632,13 @@ func (w *LogWriter) Close() error {
return cerr
}
}

for _, b := range free {
b.flushed = 0
b.written.Store(0)
blockPool.Put(b)
}

w.err = errClosedWriter
return err
}
Expand Down

0 comments on commit 2e84c30

Please sign in to comment.