Commit 5e3674ca authored by Jonathan Coens's avatar Jonathan Coens Committed by Jordan DeLong

Soft-limit for arenas

Summary: Create an artificial limit on an arena to start throwing bad_alloc before running out of system memory

Test Plan: adjust unit test

Reviewed By: marcelo.juchem@fb.com

FB internal diff: D762695
parent 005a6c1f
......@@ -45,6 +45,13 @@ template <class Alloc>
void* Arena<Alloc>::allocateSlow(size_t size) {
std::pair<Block*, size_t> p;
char* start;
size_t allocSize = std::max(size, minBlockSize()) + sizeof(Block);
if(sizeLimit_ && allocSize > sizeLimit_ - totalAllocatedSize_) {
throw std::bad_alloc();
}
if (size > minBlockSize()) {
// Allocate a large block for this chunk only, put it at the back of the
// list so it doesn't get used for small allocations; don't change ptr_
......
......@@ -60,12 +60,14 @@ template <class Alloc>
class Arena {
public:
explicit Arena(const Alloc& alloc,
size_t minBlockSize = kDefaultMinBlockSize)
size_t minBlockSize = kDefaultMinBlockSize,
size_t sizeLimit = 0)
: allocAndSize_(alloc, minBlockSize)
, ptr_(nullptr)
, end_(nullptr)
, totalAllocatedSize_(0)
, bytesUsed_(0) {
, bytesUsed_(0)
, sizeLimit_(sizeLimit) {
}
~Arena();
......@@ -192,6 +194,7 @@ class Arena {
char* end_;
size_t totalAllocatedSize_;
size_t bytesUsed_;
size_t sizeLimit_;
};
/**
......@@ -231,8 +234,10 @@ struct ArenaAllocatorTraits<SysAlloc> {
*/
class SysArena : public Arena<SysAlloc> {
public:
explicit SysArena(size_t minBlockSize = kDefaultMinBlockSize)
: Arena<SysAlloc>(SysAlloc(), minBlockSize) {
explicit SysArena(
size_t minBlockSize = kDefaultMinBlockSize,
size_t sizeLimit = 0)
: Arena<SysAlloc>(SysAlloc(), minBlockSize, sizeLimit) {
}
};
......
......@@ -142,6 +142,17 @@ TEST(Arena, Vector) {
}
}
TEST(Arena, SizeLimit) {
static const size_t requestedBlockSize = sizeof(size_t);
static const size_t maxSize = 10 * requestedBlockSize;
SysArena arena(requestedBlockSize, maxSize);
void* a = arena.allocate(sizeof(size_t));
EXPECT_TRUE(a != nullptr);
EXPECT_THROW(arena.allocate(maxSize + 1), std::bad_alloc);
}
int main(int argc, char *argv[]) {
testing::InitGoogleTest(&argc, argv);
google::ParseCommandLineFlags(&argc, &argv, true);
......
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