facebook / facebook/rocksdb

Write latency spikes in memtable

Open
#4,477 6 comments 1 reaction 0 assignees View on GitHub
Dominant language
C++
Stars
32.1k
Forks
6.9k
Avg merge
32m
Merged PRs (30d)
1

Description

Hi, I'm trying to reduce the max write latency to be less than 5ms recently (no wal sync).
I enable the perf context and find out that the `wal_time` and `memtable_time` can take more than 10ms sometimes. While the `wal_time` may or may not be avoidable since it needs to write back to the disk anyway, I expect that there may be some improvement in the `memtable_time`.

I write a simple test snippet:

```C++
#include
#include

#include "db/memtable.h"
#include "util/gflags_compat.h"

using namespace rocksdb;
using namespace std::chrono;

using GFLAGS_NAMESPACE::ParseCommandLineFlags;

DEFINE_int64(num_keys, 1 << 20, "Number of keys");
DEFINE_int64(key_size, 16, "Key size");
DEFINE_int64(value_size, 1024, "Value size");
DEFINE_int64(write_buffer_size, 128 << 20, "Write buffer size");

void GenerateString(std::string* s, uint64_t size) {
s->resize(size);
for (uint64_t i = 0; i < size; i++) {
(*s)[i] = i;
}
}

class Tracer {
public:
Tracer() {
start_ = steady_clock::now();
}

~Tracer() {
auto end = steady_clock::now();
auto elapsed = duration_cast(end - start_).count();
printf("cost %d\n", (int) elapsed);
}

private:
steady_clock::time_point start_;
};

int main(int argc, char* argv[]) {
ParseCommandLineFlags(&argc, &argv, true);

Options opts;
opts.write_buffer_size = FLAGS_write_buffer_size;
opts.arena_block_size = opts.write_buffer_size / 8;
MutableCFOptions mopts(opts);
ImmutableCFOptions iopts(opts);
auto cmp = BytewiseComparator();
InternalKeyComparator icmp(cmp);

std::string key, value;
GenerateString(&key, FLAGS_key_size);
GenerateString(&value, FLAGS_value_size);
auto num_keys_per_memtable =
opts.write_buffer_size / (FLAGS_key_size + FLAGS_value_size);

for (size_t i = 0; i < FLAGS_num_keys; i += num_keys_per_memtable) {
MemTable table(icmp, iopts, mopts, nullptr, 0, 0);
for (size_t k = i; k < i + num_keys_per_memtable; k++) {
std::random_shuffle(key.begin(), key.end());
std::random_shuffle(value.begin(), value.end());
Tracer tracer;
table.Add(k, kTypeValue, key, value);
}
}
}
```

After some investigation, seems arena allocation and `RecomputeSpliceLevels` can take more than 5ms or even 10ms sometimes. The arena allocation problem may be related to the `allocstall` and `compact_stall` showed in vmstat. I try to disable THP but it doesn't seem helpful. So is this expected or any suggestion?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.