-
Notifications
You must be signed in to change notification settings - Fork 473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sstable: reduce writer allocations during index flushing #1379
Conversation
This extends BenchmarkWriter to test block sizes as well as compressions, and generates names based on the parameters. Additionally it Close()'s the Writer since some writes are deferred until Close but should be included in the overall benchmark numbers. Finally, the discardWriter is extended to include a written byte counter to provide MB/s metrics to the benchmark.
9a3bb51
to
fc14850
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 1 files at r1, 1 of 1 files at r2, all commit messages.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @dt)
sstable/writer.go, line 536 at r2 (raw file):
w.indexBlockAlloc = make([]byte, len(bk)*16) } else { w.indexBlockAlloc = make([]byte, len(bk)*32)
how deliberate or empirical is the choice of these constants and the splitting of these two cases? wonder if it's worth the special casing, or if it is, we should do something adaptive (eg, 2 × the size of our previous indexBlockAlloc
allocation)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @jbowens)
sstable/writer.go, line 536 at r2 (raw file):
Previously, jbowens (Jackson Owens) wrote…
how deliberate or empirical is the choice of these constants and the splitting of these two cases? wonder if it's worth the special casing, or if it is, we should do something adaptive (eg, 2 × the size of our previous
indexBlockAlloc
allocation)
Oh, I'm not actually sure I meant to leave the two cases here. I might just make it a constant 16 for now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @dt)
sstable/writer.go, line 536 at r2 (raw file):
Previously, dt (David Taylor) wrote…
Oh, I'm not actually sure I meant to leave the two cases here. I might just make it a constant 16 for now?
sgtm
While working on a separate change that included passing a large number of pre-generated blocks all to addIndexEntry in a tight loop, some of the allocations it was doing per block flushed became more apparent in profiles. By batch allocating keys used as separators, and by adjusting the buffering of filled sub-index blocks to store there finished byte representation (also batch allocated) and relevant details, rather than the whole block writer used for that sub-index block, that blockWriter can instead be reused, which importantly allows reuse of its allocated buffers for things like restarts, eliminating a significant source of allocations for when flushing many sub-index blocks. ``` name old time/op new time/op delta Writer/block=4.0_K/filter=false/compression=NoCompression-10 50.4ms ± 0% 50.4ms ± 1% ~ (p=0.730 n=4+5) Writer/block=4.0_K/filter=false/compression=Snappy-10 62.6ms ± 2% 62.1ms ± 1% ~ (p=0.222 n=5+5) Writer/block=32_K/filter=false/compression=NoCompression-10 48.1ms ± 0% 48.5ms ± 0% +0.73% (p=0.008 n=5+5) Writer/block=32_K/filter=false/compression=Snappy-10 59.0ms ± 3% 58.1ms ± 2% ~ (p=0.690 n=5+5) name old speed new speed delta Writer/block=4.0_K/filter=false/compression=NoCompression-10 759MB/s ± 0% 759MB/s ± 1% ~ (p=0.730 n=4+5) Writer/block=4.0_K/filter=false/compression=Snappy-10 156MB/s ± 2% 157MB/s ± 1% ~ (p=0.222 n=5+5) Writer/block=32_K/filter=false/compression=NoCompression-10 785MB/s ± 0% 779MB/s ± 0% -0.73% (p=0.008 n=5+5) Writer/block=32_K/filter=false/compression=Snappy-10 115MB/s ± 3% 117MB/s ± 2% ~ (p=0.690 n=5+5) name old alloc/op new alloc/op delta Writer/block=4.0_K/filter=false/compression=NoCompression-10 1.18MB ± 0% 0.80MB ± 0% -32.14% (p=0.008 n=5+5) Writer/block=4.0_K/filter=false/compression=Snappy-10 1.20MB ± 0% 0.83MB ± 0% -31.08% (p=0.008 n=5+5) Writer/block=32_K/filter=false/compression=NoCompression-10 252kB ± 0% 952kB ± 0% +278.63% (p=0.008 n=5+5) Writer/block=32_K/filter=false/compression=Snappy-10 456kB ± 0% 1157kB ± 0% +153.58% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Writer/block=4.0_K/filter=false/compression=NoCompression-10 10.7k ± 0% 0.1k ± 0% -99.03% (p=0.008 n=5+5) Writer/block=4.0_K/filter=false/compression=Snappy-10 10.7k ± 0% 0.1k ± 0% -98.97% (p=0.008 n=5+5) Writer/block=32_K/filter=false/compression=NoCompression-10 1.27k ± 0% 0.10k ± 0% ~ (p=0.079 n=4+5) Writer/block=32_K/filter=false/compression=Snappy-10 1.27k ± 0% 0.10k ± 0% -91.84% (p=0.008 n=5+5) ```
fc14850
to
bd9b59c
Compare
TFTR! |
While working on a separate change that included passing a large number
of pre-generated blocks all to
addIndexEntry
in a tight loop, some ofthe allocations it was doing per block flushed became much more apparent in
profiles. By batch allocating keys used as separators, and by adjusting
the buffering of filled sub-index blocks to store their finished byte
representation (also batch allocated) with relevant details, rather than
the whole block writer, that blockWriter can instead be reused, which
importantly allows reuse of its allocated buffers eliminating a significant source of
allocations.
There overall performance impact to Writer is negligible but was more pronounced
in another change that flushes blocks in a tight loop.