Commit 817e76cb authored by Sergey Doroshenko's avatar Sergey Doroshenko Committed by Jordan DeLong

Add bytesUsed() to folly::Arena

Summary:
Returns number of bytes "really used by the user", i.e. number of bytes
allocated on the arena via calls to `allocate()`.

Test Plan: compiled, unit tests

Reviewed By: azzolini@fb.com

FB internal diff: D636976
parent 4b1e7193
...@@ -61,16 +61,18 @@ class Arena { ...@@ -61,16 +61,18 @@ class Arena {
public: public:
explicit Arena(const Alloc& alloc, explicit Arena(const Alloc& alloc,
size_t minBlockSize = kDefaultMinBlockSize) size_t minBlockSize = kDefaultMinBlockSize)
: allocAndSize_(alloc, minBlockSize), : allocAndSize_(alloc, minBlockSize)
ptr_(nullptr), , ptr_(nullptr)
end_(nullptr), , end_(nullptr)
totalAllocatedSize_(0) { , totalAllocatedSize_(0)
, bytesUsed_(0) {
} }
~Arena(); ~Arena();
void* allocate(size_t size) { void* allocate(size_t size) {
size = roundUp(size); size = roundUp(size);
bytesUsed_ += size;
if (LIKELY(end_ - ptr_ >= size)) { if (LIKELY(end_ - ptr_ >= size)) {
// Fast path: there's enough room in the current block // Fast path: there's enough room in the current block
...@@ -98,6 +100,14 @@ class Arena { ...@@ -98,6 +100,14 @@ class Arena {
return totalAllocatedSize_ + sizeof(Arena); return totalAllocatedSize_ + sizeof(Arena);
} }
// Gets the total number of "used" bytes, i.e. bytes that the arena users
// allocated via the calls to `allocate`. Doesn't include fragmentation, e.g.
// if block size is 4KB and you allocate 2 objects of 3KB in size,
// `bytesUsed()` will be 6KB, while `totalSize()` will be 8KB+.
size_t bytesUsed() const {
return bytesUsed_;
}
private: private:
// not copyable // not copyable
Arena(const Arena&) = delete; Arena(const Arena&) = delete;
...@@ -181,6 +191,7 @@ class Arena { ...@@ -181,6 +191,7 @@ class Arena {
char* ptr_; char* ptr_;
char* end_; char* end_;
size_t totalAllocatedSize_; size_t totalAllocatedSize_;
size_t bytesUsed_;
}; };
/** /**
......
...@@ -84,6 +84,46 @@ TEST(Arena, SizeSanity) { ...@@ -84,6 +84,46 @@ TEST(Arena, SizeSanity) {
<< maximum_size; << maximum_size;
} }
TEST(Arena, BytesUsedSanity) {
static const size_t smallChunkSize = 1024;
static const size_t blockSize = goodMallocSize(16 * smallChunkSize);
const size_t bigChunkSize = blockSize - 4 * smallChunkSize;
size_t bytesUsed = 0;
SysArena arena(blockSize);
EXPECT_EQ(arena.bytesUsed(), bytesUsed);
// Insert 2 small chunks
arena.allocate(smallChunkSize);
arena.allocate(smallChunkSize);
bytesUsed += 2 * smallChunkSize;
EXPECT_EQ(arena.bytesUsed(), bytesUsed);
EXPECT_TRUE(arena.totalSize() >= blockSize);
EXPECT_TRUE(arena.totalSize() <= 2 * blockSize);
// Insert big chunk, should still fit in one block
arena.allocate(bigChunkSize);
bytesUsed += bigChunkSize;
EXPECT_EQ(arena.bytesUsed(), bytesUsed);
EXPECT_TRUE(arena.totalSize() >= blockSize);
EXPECT_TRUE(arena.totalSize() <= 2 * blockSize);
// Insert big chunk once more, should trigger new block allocation
arena.allocate(bigChunkSize);
bytesUsed += bigChunkSize;
EXPECT_EQ(arena.bytesUsed(), bytesUsed);
EXPECT_TRUE(arena.totalSize() >= 2 * blockSize);
EXPECT_TRUE(arena.totalSize() <= 3 * blockSize);
// Test that bytesUsed() accounts for alignment
static const size_t tinyChunkSize = 7;
arena.allocate(tinyChunkSize);
EXPECT_TRUE(arena.bytesUsed() >= bytesUsed + tinyChunkSize);
size_t delta = arena.bytesUsed() - bytesUsed;
EXPECT_EQ(delta & (delta - 1), 0);
}
TEST(Arena, Vector) { TEST(Arena, Vector) {
static const size_t requestedBlockSize = 64; static const size_t requestedBlockSize = 64;
SysArena arena(requestedBlockSize); SysArena arena(requestedBlockSize);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment