Write latency spikes in memtable
- 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
Assessment
This issue has not been assessed yet.