Eliminate a memcpy for uncompressed blocks

Summary:
`ReadBlockFromFile` uses a stack buffer to hold small data blocks before passing them to the compression library, which outputs uncompressed data in a heap buffer. In the case of `kNoCompression` there is a `memcpy` to copy from stack buffer to heap buffer.

This PR optimizes `ReadBlockFromFile` to skip the stack buffer for files whose blocks are known to be uncompressed. We determine this using the SST file property, "compression_name", if it's available.
Closes https://github.com/facebook/rocksdb/pull/3472

Differential Revision: D6920848

Pulled By: ajkr

fbshipit-source-id: 5c753e804efc178b9229ae5dbe6a4adc32031f07
main
Andrew Kryczka 7 years ago committed by Facebook Github Bot
parent a0931b3185
commit e78715c29a
  1. 18
      table/block_based_table_reader.cc
  2. 6
      table/block_based_table_reader.h

@ -759,7 +759,10 @@ Status BlockBasedTable::Open(const ImmutableCFOptions& ioptions,
"block %s", "block %s",
s.ToString().c_str()); s.ToString().c_str());
} else { } else {
assert(table_properties != nullptr);
rep->table_properties.reset(table_properties); rep->table_properties.reset(table_properties);
rep->blocks_maybe_compressed = rep->table_properties->compression_name !=
CompressionTypeToString(kNoCompression);
} }
} else { } else {
ROCKS_LOG_ERROR(rep->ioptions.info_log, ROCKS_LOG_ERROR(rep->ioptions.info_log,
@ -769,7 +772,7 @@ Status BlockBasedTable::Open(const ImmutableCFOptions& ioptions,
// Read the compression dictionary meta block // Read the compression dictionary meta block
bool found_compression_dict; bool found_compression_dict;
BlockHandle compression_dict_handle; BlockHandle compression_dict_handle;
s = SeekToCompressionDictBlock(meta_iter.get(), &found_compression_dict, s = SeekToCompressionDictBlock(meta_iter.get(), &found_compression_dict,
&compression_dict_handle); &compression_dict_handle);
if (!s.ok()) { if (!s.ok()) {
ROCKS_LOG_WARN( ROCKS_LOG_WARN(
@ -1502,11 +1505,11 @@ BlockIter* BlockBasedTable::NewDataBlockIterator(
{ {
StopWatch sw(rep->ioptions.env, rep->ioptions.statistics, StopWatch sw(rep->ioptions.env, rep->ioptions.statistics,
READ_BLOCK_GET_MICROS); READ_BLOCK_GET_MICROS);
s = ReadBlockFromFile( s = ReadBlockFromFile(rep->file.get(), nullptr /* prefetch_buffer */,
rep->file.get(), nullptr /* prefetch_buffer */, rep->footer, ro, rep->footer, ro, handle, &block_value, rep->ioptions,
handle, &block_value, rep->ioptions, true /* compress */, rep->blocks_maybe_compressed, compression_dict,
compression_dict, rep->persistent_cache_options, rep->global_seqno, rep->persistent_cache_options, rep->global_seqno,
rep->table_options.read_amp_bytes_per_bit); rep->table_options.read_amp_bytes_per_bit);
} }
if (s.ok()) { if (s.ok()) {
block.value = block_value.release(); block.value = block_value.release();
@ -1605,7 +1608,8 @@ Status BlockBasedTable::MaybeLoadDataBlockToCache(
StopWatch sw(rep->ioptions.env, statistics, READ_BLOCK_GET_MICROS); StopWatch sw(rep->ioptions.env, statistics, READ_BLOCK_GET_MICROS);
s = ReadBlockFromFile( s = ReadBlockFromFile(
rep->file.get(), prefetch_buffer, rep->footer, ro, handle, rep->file.get(), prefetch_buffer, rep->footer, ro, handle,
&raw_block, rep->ioptions, block_cache_compressed == nullptr, &raw_block, rep->ioptions,
block_cache_compressed == nullptr && rep->blocks_maybe_compressed,
compression_dict, rep->persistent_cache_options, rep->global_seqno, compression_dict, rep->persistent_cache_options, rep->global_seqno,
rep->table_options.read_amp_bytes_per_bit); rep->table_options.read_amp_bytes_per_bit);
} }

@ -224,6 +224,7 @@ class BlockBasedTable : public TableReader {
Rep* rep, const ReadOptions& ro, const BlockHandle& block_hanlde, Rep* rep, const ReadOptions& ro, const BlockHandle& block_hanlde,
BlockIter* input_iter = nullptr, bool is_index = false, BlockIter* input_iter = nullptr, bool is_index = false,
GetContext* get_context = nullptr, Status s = Status()); GetContext* get_context = nullptr, Status s = Status());
// If block cache enabled (compressed or uncompressed), looks for the block // If block cache enabled (compressed or uncompressed), looks for the block
// identified by handle in (1) uncompressed cache, (2) compressed cache, and // identified by handle in (1) uncompressed cache, (2) compressed cache, and
// then (3) file. If found, inserts into the cache(s) that were searched // then (3) file. If found, inserts into the cache(s) that were searched
@ -495,6 +496,11 @@ struct BlockBasedTable::Rep {
// A value of kDisableGlobalSequenceNumber means that this feature is disabled // A value of kDisableGlobalSequenceNumber means that this feature is disabled
// and every key have it's own seqno. // and every key have it's own seqno.
SequenceNumber global_seqno; SequenceNumber global_seqno;
// If false, blocks in this file are definitely all uncompressed. Knowing this
// before reading individual blocks enables certain optimizations.
bool blocks_maybe_compressed = true;
bool closed = false; bool closed = false;
}; };

Loading…
Cancel
Save