2016-02-09 23:12:00 +00:00
|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
2013-12-03 02:34:05 +00:00
|
|
|
// This source code is licensed under the BSD-style license found in the
|
|
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
// of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include "db/dbformat.h"
|
|
|
|
#include "rocksdb/slice.h"
|
|
|
|
#include <string>
|
|
|
|
#include <deque>
|
|
|
|
|
|
|
|
namespace rocksdb {
|
|
|
|
|
|
|
|
const std::deque<std::string> empty_operand_list;
|
|
|
|
|
|
|
|
// The merge context for merging a user key.
|
|
|
|
// When doing a Get(), DB will create such a class and pass it when
|
|
|
|
// issuing Get() operation to memtables and version_set. The operands
|
|
|
|
// will be fetched from the context when issuing partial of full merge.
|
|
|
|
class MergeContext {
|
|
|
|
public:
|
|
|
|
// Clear all the operands
|
|
|
|
void Clear() {
|
|
|
|
if (operand_list) {
|
|
|
|
operand_list->clear();
|
|
|
|
}
|
|
|
|
}
|
2014-03-25 00:57:13 +00:00
|
|
|
// Replace all operands with merge_result, which are expected to be the
|
|
|
|
// merge result of them.
|
2013-12-03 02:34:05 +00:00
|
|
|
void PushPartialMergeResult(std::string& merge_result) {
|
|
|
|
assert (operand_list);
|
2014-03-25 00:57:13 +00:00
|
|
|
operand_list->clear();
|
|
|
|
operand_list->push_front(std::move(merge_result));
|
2013-12-03 02:34:05 +00:00
|
|
|
}
|
|
|
|
// Push a merge operand
|
|
|
|
void PushOperand(const Slice& operand_slice) {
|
|
|
|
Initialize();
|
|
|
|
operand_list->push_front(operand_slice.ToString());
|
|
|
|
}
|
Eliminate std::deque initialization while iterating over merge operands
Summary:
This patch is similar to D52563, When we iterate over a DB with merge operands we keep creating std::queue to store the operands, optimize this by reusing merge_operands_ data member
Before the patch
```
./db_bench --benchmarks="mergerandom,readseq,readseq,readseq,readseq" --db="/dev/shm/bench_merge_memcpy_on_the_fly/" --merge_operator="put" --merge_keys=10000 --num=10000
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
mergerandom : 3.757 micros/op 266141 ops/sec; 29.4 MB/s ( updates:10000)
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.413 micros/op 2423538 ops/sec; 268.1 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.451 micros/op 2219071 ops/sec; 245.5 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.420 micros/op 2382039 ops/sec; 263.5 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.408 micros/op 2452017 ops/sec; 271.3 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
mergerandom : 3.947 micros/op 253376 ops/sec; 28.0 MB/s ( updates:10000)
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.441 micros/op 2266473 ops/sec; 250.7 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.471 micros/op 2122033 ops/sec; 234.8 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.440 micros/op 2271407 ops/sec; 251.3 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.429 micros/op 2331471 ops/sec; 257.9 MB/s
```
with the patch
```
./db_bench --benchmarks="mergerandom,readseq,readseq,readseq,readseq" --db="/dev/shm/bench_merge_memcpy_on_the_fly/" --merge_operator="put" --merge_keys=10000 --num=10000
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
mergerandom : 4.080 micros/op 245092 ops/sec; 27.1 MB/s ( updates:10000)
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.308 micros/op 3241843 ops/sec; 358.6 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.312 micros/op 3200408 ops/sec; 354.0 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.332 micros/op 3013962 ops/sec; 333.4 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.300 micros/op 3328017 ops/sec; 368.2 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
mergerandom : 3.973 micros/op 251705 ops/sec; 27.8 MB/s ( updates:10000)
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.320 micros/op 3123752 ops/sec; 345.6 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.335 micros/op 2986641 ops/sec; 330.4 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.339 micros/op 2950047 ops/sec; 326.4 MB/s
DB path: [/dev/shm/bench_merge_memcpy_on_the_fly/]
readseq : 0.319 micros/op 3131565 ops/sec; 346.4 MB/s
```
Test Plan: make check -j64
Reviewers: yhchiang, andrewkr, sdong
Reviewed By: sdong
Subscribers: andrewkr, dhruba
Differential Revision: https://reviews.facebook.net/D56031
2016-04-01 22:48:55 +00:00
|
|
|
// Push back a merge operand
|
|
|
|
void PushOperandBack(const Slice& operand_slice) {
|
|
|
|
Initialize();
|
|
|
|
operand_list->push_back(operand_slice.ToString());
|
|
|
|
}
|
2013-12-03 02:34:05 +00:00
|
|
|
// return total number of operands in the list
|
|
|
|
size_t GetNumOperands() const {
|
|
|
|
if (!operand_list) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return operand_list->size();
|
|
|
|
}
|
|
|
|
// Get the operand at the index.
|
|
|
|
Slice GetOperand(int index) const {
|
|
|
|
assert (operand_list);
|
|
|
|
return (*operand_list)[index];
|
|
|
|
}
|
|
|
|
// Return all the operands.
|
|
|
|
const std::deque<std::string>& GetOperands() const {
|
|
|
|
if (!operand_list) {
|
|
|
|
return empty_operand_list;
|
|
|
|
}
|
|
|
|
return *operand_list;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
void Initialize() {
|
|
|
|
if (!operand_list) {
|
|
|
|
operand_list.reset(new std::deque<std::string>());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::unique_ptr<std::deque<std::string>> operand_list;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace rocksdb
|