mirror of
https://github.com/facebook/rocksdb.git
synced 2024-11-30 04:41:49 +00:00
f3cc66632b
Summary: Try to align the compaction output file boundaries to the next level ones (grandparent level), to reduce the level compaction write-amplification. In level compaction, there are "wasted" data at the beginning and end of the output level files. Align the file boundary can avoid such "wasted" compaction. With this PR, it tries to align the non-bottommost level file boundaries to its next level ones. It may cut file when the file size is large enough (at least 50% of target_file_size) and not too large (2x target_file_size). db_bench shows about 12.56% compaction reduction: ``` TEST_TMPDIR=/data/dbbench2 ./db_bench --benchmarks=fillrandom,readrandom -max_background_jobs=12 -num=400000000 -target_file_size_base=33554432 # baseline: Flush(GB): cumulative 25.882, interval 7.216 Cumulative compaction: 285.90 GB write, 162.36 MB/s write, 269.68 GB read, 153.15 MB/s read, 2926.7 seconds # with this change: Flush(GB): cumulative 25.882, interval 7.753 Cumulative compaction: 249.97 GB write, 141.96 MB/s write, 233.74 GB read, 132.74 MB/s read, 2534.9 seconds ``` The compaction simulator shows a similar result (14% with 100G random data). As a side effect, with this PR, the SST file size can exceed the target_file_size, but is capped at 2x target_file_size. And there will be smaller files. Here are file size statistics when loading 100GB with the target file size 32MB: ``` baseline this_PR count 1.656000e+03 1.705000e+03 mean 3.116062e+07 3.028076e+07 std 7.145242e+06 8.046139e+06 ``` The feature is enabled by default, to revert to the old behavior disable it with `AdvancedColumnFamilyOptions.level_compaction_dynamic_file_size = false` Also includes https://github.com/facebook/rocksdb/issues/1963 to cut file before skippable grandparent file. Which is for use case like user adding 2 or more non-overlapping data range at the same time, it can reduce the overlapping of 2 datasets in the lower levels. Pull Request resolved: https://github.com/facebook/rocksdb/pull/10655 Reviewed By: cbi42 Differential Revision: D39552321 Pulled By: jay-zhuang fbshipit-source-id: 640d15f159ab0cd973f2426cfc3af266fc8bdde2
95 lines
3.1 KiB
C++
95 lines
3.1 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <atomic>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <set>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include "db/version_edit.h"
|
|
#include "port/port.h"
|
|
#include "rocksdb/comparator.h"
|
|
#include "rocksdb/io_status.h"
|
|
#include "rocksdb/table.h"
|
|
#include "table/internal_iterator.h"
|
|
#include "table/table_builder.h"
|
|
#include "table/table_reader.h"
|
|
#include "test_util/testharness.h"
|
|
#include "test_util/testutil.h"
|
|
#include "util/kv_map.h"
|
|
#include "util/mutexlock.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
namespace mock {
|
|
using KVPair = std::pair<std::string, std::string>;
|
|
using KVVector = std::vector<KVPair>;
|
|
|
|
KVVector MakeMockFile(std::initializer_list<KVPair> l = {});
|
|
void SortKVVector(KVVector* kv_vector,
|
|
const Comparator* ucmp = BytewiseComparator());
|
|
|
|
struct MockTableFileSystem {
|
|
port::Mutex mutex;
|
|
std::map<uint32_t, KVVector> files;
|
|
};
|
|
|
|
class MockTableFactory : public TableFactory {
|
|
public:
|
|
enum MockCorruptionMode {
|
|
kCorruptNone,
|
|
kCorruptKey,
|
|
kCorruptValue,
|
|
kCorruptReorderKey,
|
|
};
|
|
|
|
MockTableFactory();
|
|
static const char* kClassName() { return "MockTable"; }
|
|
const char* Name() const override { return kClassName(); }
|
|
using TableFactory::NewTableReader;
|
|
Status NewTableReader(
|
|
const ReadOptions& ro, const TableReaderOptions& table_reader_options,
|
|
std::unique_ptr<RandomAccessFileReader>&& file, uint64_t file_size,
|
|
std::unique_ptr<TableReader>* table_reader,
|
|
bool prefetch_index_and_filter_in_cache = true) const override;
|
|
TableBuilder* NewTableBuilder(
|
|
const TableBuilderOptions& table_builder_options,
|
|
WritableFileWriter* file) const override;
|
|
|
|
// This function will directly create mock table instead of going through
|
|
// MockTableBuilder. file_contents has to have a format of <internal_key,
|
|
// value>. Those key-value pairs will then be inserted into the mock table.
|
|
Status CreateMockTable(Env* env, const std::string& fname,
|
|
KVVector file_contents);
|
|
|
|
virtual std::string GetPrintableOptions() const override {
|
|
return std::string();
|
|
}
|
|
|
|
void SetCorruptionMode(MockCorruptionMode mode) { corrupt_mode_ = mode; }
|
|
|
|
void SetKeyValueSize(size_t size) { key_value_size_ = size; }
|
|
// This function will assert that only a single file exists and that the
|
|
// contents are equal to file_contents
|
|
void AssertSingleFile(const KVVector& file_contents);
|
|
void AssertLatestFiles(const std::vector<KVVector>& files_contents);
|
|
|
|
private:
|
|
Status GetAndWriteNextID(WritableFileWriter* file, uint32_t* id) const;
|
|
Status GetIDFromFile(RandomAccessFileReader* file, uint32_t* id) const;
|
|
|
|
mutable MockTableFileSystem file_system_;
|
|
mutable std::atomic<uint32_t> next_id_;
|
|
MockCorruptionMode corrupt_mode_;
|
|
|
|
size_t key_value_size_ = 1;
|
|
};
|
|
|
|
} // namespace mock
|
|
} // namespace ROCKSDB_NAMESPACE
|