Skip to content

Commit 706b7f8

Browse files
ssiddharthacmumford
authored andcommitted
Resolve race when getting approximate-memory-usage property
The write operations in the table happens without holding the mutex lock, but concurrent writes are avoided using "writers_" queue. The Arena::MemoryUsage could access the blocks when write happens. So, the memory usage is cached in atomic word and can be loaded from any thread safely. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=107573379
1 parent 3c9ff3c commit 706b7f8

File tree

3 files changed

+9
-12
lines changed

3 files changed

+9
-12
lines changed

db/memtable.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ class MemTable {
3636
}
3737

3838
// Returns an estimate of the number of bytes of data in use by this
39-
// data structure.
40-
//
41-
// REQUIRES: external synchronization to prevent simultaneous
42-
// operations on the same MemTable.
39+
// data structure. It is safe to call when MemTable is being modified.
4340
size_t ApproximateMemoryUsage();
4441

4542
// Return an iterator that yields the contents of the memtable.

util/arena.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ namespace leveldb {
99

1010
static const int kBlockSize = 4096;
1111

12-
Arena::Arena() {
13-
blocks_memory_ = 0;
12+
Arena::Arena() : memory_usage_(0) {
1413
alloc_ptr_ = NULL; // First allocation will allocate a block
1514
alloc_bytes_remaining_ = 0;
1615
}
@@ -60,8 +59,9 @@ char* Arena::AllocateAligned(size_t bytes) {
6059

6160
char* Arena::AllocateNewBlock(size_t block_bytes) {
6261
char* result = new char[block_bytes];
63-
blocks_memory_ += block_bytes;
6462
blocks_.push_back(result);
63+
memory_usage_.NoBarrier_Store(
64+
reinterpret_cast<void*>(MemoryUsage() + block_bytes + sizeof(char*)));
6565
return result;
6666
}
6767

util/arena.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <assert.h>
1010
#include <stddef.h>
1111
#include <stdint.h>
12+
#include "port/port.h"
1213

1314
namespace leveldb {
1415

@@ -24,10 +25,9 @@ class Arena {
2425
char* AllocateAligned(size_t bytes);
2526

2627
// Returns an estimate of the total memory usage of data allocated
27-
// by the arena (including space allocated but not yet used for user
28-
// allocations).
28+
// by the arena.
2929
size_t MemoryUsage() const {
30-
return blocks_memory_ + blocks_.capacity() * sizeof(char*);
30+
return reinterpret_cast<uintptr_t>(memory_usage_.NoBarrier_Load());
3131
}
3232

3333
private:
@@ -41,8 +41,8 @@ class Arena {
4141
// Array of new[] allocated memory blocks
4242
std::vector<char*> blocks_;
4343

44-
// Bytes of memory in blocks allocated so far
45-
size_t blocks_memory_;
44+
// Total memory usage of the arena.
45+
port::AtomicPointer memory_usage_;
4646

4747
// No copying allowed
4848
Arena(const Arena&);

0 commit comments

Comments
 (0)