Reorder DBIter fields to reduce memory usage (#5078)

Summary:
The patch reorders DBIter fields to put 1-byte fields together and let the compiler optimize the memory usage by using less 64-bit allocations for bools and enums.

This might have a negative side effect of putting the variables that are accessed together into different cache lines and hence increasing the cache misses. Not sure what benchmark would verify that thought. I ran simple, single-threaded seekrandom benchmarks but the variance in the results is too much to be conclusive.

./db_bench --benchmarks=fillrandom --use_existing_db=0 --num=1000000 --db=/dev/shm/dbbench
./db_bench --benchmarks=seekrandom[X10] --use_existing_db=1 --db=/dev/shm/dbbench --num=1000000 --duration=60 --seek_nexts=100
Pull Request resolved: https://github.com/facebook/rocksdb/pull/5078

Differential Revision: D14562676

Pulled By: maysamyabandeh

fbshipit-source-id: 2284655d46e079b6e9a860e94be5defb6f482167
main
Maysam Yabandeh 6 years ago committed by Facebook Github Bot
parent 34f8ac0c99
commit c84fad7a19
  1. 34
      db/db_iter.cc
  2. 4
      db/dbformat.h

@ -117,29 +117,29 @@ class DBIter final: public Iterator {
uint64_t max_sequential_skip_in_iterations, uint64_t max_sequential_skip_in_iterations,
ReadCallback* read_callback, DBImpl* db_impl, ColumnFamilyData* cfd, ReadCallback* read_callback, DBImpl* db_impl, ColumnFamilyData* cfd,
bool allow_blob) bool allow_blob)
: arena_mode_(arena_mode), : env_(_env),
env_(_env),
logger_(cf_options.info_log), logger_(cf_options.info_log),
user_comparator_(cmp), user_comparator_(cmp),
merge_operator_(cf_options.merge_operator), merge_operator_(cf_options.merge_operator),
iter_(iter), iter_(iter),
read_callback_(read_callback),
sequence_(s), sequence_(s),
direction_(kForward),
valid_(false),
current_entry_is_merged_(false),
statistics_(cf_options.statistics), statistics_(cf_options.statistics),
num_internal_keys_skipped_(0), num_internal_keys_skipped_(0),
iterate_lower_bound_(read_options.iterate_lower_bound), iterate_lower_bound_(read_options.iterate_lower_bound),
iterate_upper_bound_(read_options.iterate_upper_bound), iterate_upper_bound_(read_options.iterate_upper_bound),
direction_(kForward),
valid_(false),
current_entry_is_merged_(false),
prefix_same_as_start_(read_options.prefix_same_as_start), prefix_same_as_start_(read_options.prefix_same_as_start),
pin_thru_lifetime_(read_options.pin_data), pin_thru_lifetime_(read_options.pin_data),
total_order_seek_(read_options.total_order_seek), total_order_seek_(read_options.total_order_seek),
allow_blob_(allow_blob),
is_blob_(false),
arena_mode_(arena_mode),
range_del_agg_(&cf_options.internal_comparator, s), range_del_agg_(&cf_options.internal_comparator, s),
read_callback_(read_callback),
db_impl_(db_impl), db_impl_(db_impl),
cfd_(cfd), cfd_(cfd),
allow_blob_(allow_blob),
is_blob_(false),
start_seqnum_(read_options.iter_start_seqnum) { start_seqnum_(read_options.iter_start_seqnum) {
RecordTick(statistics_, NO_ITERATOR_CREATED); RecordTick(statistics_, NO_ITERATOR_CREATED);
prefix_extractor_ = mutable_cf_options.prefix_extractor.get(); prefix_extractor_ = mutable_cf_options.prefix_extractor.get();
@ -304,15 +304,14 @@ class DBIter final: public Iterator {
} }
const SliceTransform* prefix_extractor_; const SliceTransform* prefix_extractor_;
bool arena_mode_;
Env* const env_; Env* const env_;
Logger* logger_; Logger* logger_;
const Comparator* const user_comparator_; const Comparator* const user_comparator_;
const MergeOperator* const merge_operator_; const MergeOperator* const merge_operator_;
InternalIterator* iter_; InternalIterator* iter_;
ReadCallback* read_callback_;
SequenceNumber sequence_; SequenceNumber sequence_;
Status status_;
IterKey saved_key_; IterKey saved_key_;
// Reusable internal key data structure. This is only used inside one function // Reusable internal key data structure. This is only used inside one function
// and should not be used across functions. Reusing this object can reduce // and should not be used across functions. Reusing this object can reduce
@ -320,9 +319,6 @@ class DBIter final: public Iterator {
ParsedInternalKey ikey_; ParsedInternalKey ikey_;
std::string saved_value_; std::string saved_value_;
Slice pinned_value_; Slice pinned_value_;
Direction direction_;
bool valid_;
bool current_entry_is_merged_;
// for prefix seek mode to support prev() // for prefix seek mode to support prev()
Statistics* statistics_; Statistics* statistics_;
uint64_t max_skip_; uint64_t max_skip_;
@ -330,23 +326,29 @@ class DBIter final: public Iterator {
uint64_t num_internal_keys_skipped_; uint64_t num_internal_keys_skipped_;
const Slice* iterate_lower_bound_; const Slice* iterate_lower_bound_;
const Slice* iterate_upper_bound_; const Slice* iterate_upper_bound_;
IterKey prefix_start_buf_; IterKey prefix_start_buf_;
Status status_;
Slice prefix_start_key_; Slice prefix_start_key_;
Direction direction_;
bool valid_;
bool current_entry_is_merged_;
const bool prefix_same_as_start_; const bool prefix_same_as_start_;
// Means that we will pin all data blocks we read as long the Iterator // Means that we will pin all data blocks we read as long the Iterator
// is not deleted, will be true if ReadOptions::pin_data is true // is not deleted, will be true if ReadOptions::pin_data is true
const bool pin_thru_lifetime_; const bool pin_thru_lifetime_;
const bool total_order_seek_; const bool total_order_seek_;
bool allow_blob_;
bool is_blob_;
bool arena_mode_;
// List of operands for merge operator. // List of operands for merge operator.
MergeContext merge_context_; MergeContext merge_context_;
ReadRangeDelAggregator range_del_agg_; ReadRangeDelAggregator range_del_agg_;
LocalStatistics local_stats_; LocalStatistics local_stats_;
PinnedIteratorsManager pinned_iters_mgr_; PinnedIteratorsManager pinned_iters_mgr_;
ReadCallback* read_callback_;
DBImpl* db_impl_; DBImpl* db_impl_;
ColumnFamilyData* cfd_; ColumnFamilyData* cfd_;
bool allow_blob_;
bool is_blob_;
// for diff snapshots we want the lower bound on the seqnum; // for diff snapshots we want the lower bound on the seqnum;
// if this value > 0 iterator will return internal keys // if this value > 0 iterator will return internal keys
SequenceNumber start_seqnum_; SequenceNumber start_seqnum_;

@ -339,9 +339,9 @@ class IterKey {
public: public:
IterKey() IterKey()
: buf_(space_), : buf_(space_),
buf_size_(sizeof(space_)),
key_(buf_), key_(buf_),
key_size_(0), key_size_(0),
buf_size_(sizeof(space_)),
is_user_key_(true) {} is_user_key_(true) {}
~IterKey() { ResetBuffer(); } ~IterKey() { ResetBuffer(); }
@ -496,9 +496,9 @@ class IterKey {
private: private:
char* buf_; char* buf_;
size_t buf_size_;
const char* key_; const char* key_;
size_t key_size_; size_t key_size_;
size_t buf_size_;
char space_[32]; // Avoid allocation for short keys char space_[32]; // Avoid allocation for short keys
bool is_user_key_; bool is_user_key_;

Loading…
Cancel
Save