}
char* Arena::AllocateNewBlock(size_t block_bytes) {
- auto uniq = std::make_unique<char[]>(block_bytes);
- char* block = uniq.get();
- blocks_.push_back(std::move(uniq));
+ // NOTE: std::make_unique zero-initializes the block so is not appropriate
+ // here
+ char* block = new char[block_bytes];
+ blocks_.push_back(std::unique_ptr<char[]>(block));
size_t allocated_size;
#ifdef ROCKSDB_MALLOC_USABLE_SIZE
}
}
+TEST_F(ArenaTest, UnmappedAllocation) {
+ // Verify that it's possible to get unmapped pages in large allocations,
+ // for memory efficiency and to ensure we don't accidentally waste time &
+ // space initializing the memory.
+ constexpr size_t kBlockSize = 2U << 20;
+ Arena arena(kBlockSize);
+
+ // The allocator might give us back recycled memory for a while, but
+ // shouldn't last forever.
+ for (int i = 0;; ++i) {
+ char* p = arena.Allocate(kBlockSize);
+
+ // Start counting page faults
+ PopMinorPageFaultCount();
+
+ // Overwrite the whole allocation
+ for (size_t j = 0; j < kBlockSize; ++j) {
+ p[j] = static_cast<char>(j & 255);
+ }
+
+ size_t faults = PopMinorPageFaultCount();
+ if (faults >= kBlockSize * 3 / 4 / port::kPageSize) {
+ // Most of the access generated page faults => GOOD
+ break;
+ }
+ // Should have succeeded after enough tries
+ ASSERT_LT(i, 1000);
+ }
+}
+
} // namespace ROCKSDB_NAMESPACE
int main(int argc, char** argv) {