xo-alloc: retire redline-memory feature
This commit is contained in:
parent
13f4fb0935
commit
2048de70f3
9 changed files with 111 additions and 11 deletions
|
|
@ -42,7 +42,9 @@ namespace xo {
|
||||||
* with reserved capacity @p redline_z.
|
* with reserved capacity @p redline_z.
|
||||||
**/
|
**/
|
||||||
static up<ArenaAlloc> make(const std::string & name,
|
static up<ArenaAlloc> make(const std::string & name,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
std::size_t redline_z,
|
std::size_t redline_z,
|
||||||
|
#endif
|
||||||
std::size_t z,
|
std::size_t z,
|
||||||
bool debug_flag);
|
bool debug_flag);
|
||||||
|
|
||||||
|
|
@ -66,10 +68,16 @@ namespace xo {
|
||||||
virtual void clear() final override;
|
virtual void clear() final override;
|
||||||
virtual void checkpoint() final override;
|
virtual void checkpoint() final override;
|
||||||
virtual std::byte * alloc(std::size_t z) final override;
|
virtual std::byte * alloc(std::size_t z) final override;
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
virtual void release_redline_memory() final override;
|
virtual void release_redline_memory() final override;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ArenaAlloc(const std::string & name, std::size_t rz, std::size_t z, bool debug_flag);
|
ArenaAlloc(const std::string & name,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
|
std::size_t rz,
|
||||||
|
#endif
|
||||||
|
std::size_t z, bool debug_flag);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
@ -91,8 +99,10 @@ namespace xo {
|
||||||
std::byte * free_ptr_ = nullptr;
|
std::byte * free_ptr_ = nullptr;
|
||||||
/** soft limit: end of released memory **/
|
/** soft limit: end of released memory **/
|
||||||
std::byte * limit_ = nullptr;
|
std::byte * limit_ = nullptr;
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
/** amount of last-resort memory to reserve **/
|
/** amount of last-resort memory to reserve **/
|
||||||
std::size_t redline_z_ = 0;
|
std::size_t redline_z_ = 0;
|
||||||
|
#endif
|
||||||
/** hard limit: end of allocated memory **/
|
/** hard limit: end of allocated memory **/
|
||||||
std::byte * hi_ = nullptr;
|
std::byte * hi_ = nullptr;
|
||||||
/** true to enable detailed debug logging **/
|
/** true to enable detailed debug logging **/
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,9 @@ namespace xo {
|
||||||
virtual std::byte * alloc(std::size_t z) final override;
|
virtual std::byte * alloc(std::size_t z) final override;
|
||||||
virtual std::byte * alloc_gc_copy(std::size_t z, const void * src) final override;
|
virtual std::byte * alloc_gc_copy(std::size_t z, const void * src) final override;
|
||||||
|
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
virtual void release_redline_memory() final override;
|
virtual void release_redline_memory() final override;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** begin GC now **/
|
/** begin GC now **/
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,10 @@ namespace xo {
|
||||||
* Only used in @ref GC. Default implementation asserts and returns nullptr
|
* Only used in @ref GC. Default implementation asserts and returns nullptr
|
||||||
**/
|
**/
|
||||||
virtual std::byte * alloc_gc_copy(std::size_t z, const void * src);
|
virtual std::byte * alloc_gc_copy(std::size_t z, const void * src);
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
/** release last-resort reserved memory **/
|
/** release last-resort reserved memory **/
|
||||||
virtual void release_redline_memory() = 0;
|
virtual void release_redline_memory() = 0;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
} /*namespace gc*/
|
} /*namespace gc*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,9 @@ namespace xo {
|
||||||
ListAlloc(std::unique_ptr<ArenaAlloc> hd,
|
ListAlloc(std::unique_ptr<ArenaAlloc> hd,
|
||||||
ArenaAlloc * marked,
|
ArenaAlloc * marked,
|
||||||
std::size_t cz, std::size_t nz, std::size_t tz,
|
std::size_t cz, std::size_t nz, std::size_t tz,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
bool use_redline,
|
bool use_redline,
|
||||||
|
#endif
|
||||||
bool debug_flag);
|
bool debug_flag);
|
||||||
~ListAlloc();
|
~ListAlloc();
|
||||||
|
|
||||||
|
|
@ -66,7 +68,9 @@ namespace xo {
|
||||||
virtual void clear() final override;
|
virtual void clear() final override;
|
||||||
virtual void checkpoint() final override;
|
virtual void checkpoint() final override;
|
||||||
virtual std::byte * alloc(std::size_t z) final override;
|
virtual std::byte * alloc(std::size_t z) final override;
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
virtual void release_redline_memory() final override;
|
virtual void release_redline_memory() final override;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** **/
|
/** **/
|
||||||
|
|
@ -79,11 +83,16 @@ namespace xo {
|
||||||
* from trying to converge on app working set size
|
* from trying to converge on app working set size
|
||||||
**/
|
**/
|
||||||
std::list<std::unique_ptr<ArenaAlloc>> full_l_;
|
std::list<std::unique_ptr<ArenaAlloc>> full_l_;
|
||||||
std::size_t current_z_ = 0;;
|
/** size of current arena @ref hd_ **/
|
||||||
std::size_t next_z_ = 0;;
|
std::size_t current_z_ = 0;
|
||||||
|
/** if @ref hd_ fills, size of next arena to allocate **/
|
||||||
|
std::size_t next_z_ = 0;
|
||||||
|
/** total size of @ref hd_ + contents of @ref full_l_ **/
|
||||||
std::size_t total_z_ = 0;
|
std::size_t total_z_ = 0;
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
bool use_redline_ = false;
|
bool use_redline_ = false;
|
||||||
bool redlined_flag_ = false;
|
bool redlined_flag_ = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
/** true to enable debug logging **/
|
/** true to enable debug logging **/
|
||||||
bool debug_flag_ = false;
|
bool debug_flag_ = false;
|
||||||
|
|
|
||||||
|
|
@ -12,20 +12,37 @@
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace gc {
|
namespace gc {
|
||||||
ArenaAlloc::ArenaAlloc(const std::string & name, std::size_t rz, std::size_t z, bool debug_flag)
|
ArenaAlloc::ArenaAlloc(const std::string & name,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
|
std::size_t rz,
|
||||||
|
#endif
|
||||||
|
std::size_t z, bool debug_flag)
|
||||||
{
|
{
|
||||||
this->name_ = name;
|
this->name_ = name;
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
this->lo_ = (new std::byte [rz + z]);
|
this->lo_ = (new std::byte [rz + z]);
|
||||||
|
#else
|
||||||
|
this->lo_ = (new std::byte [z]);
|
||||||
|
#endif
|
||||||
this->checkpoint_ = lo_;
|
this->checkpoint_ = lo_;
|
||||||
this->free_ptr_ = lo_;
|
this->free_ptr_ = lo_;
|
||||||
this->limit_ = lo_ + z;
|
this->limit_ = lo_ + z;
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
this->redline_z_ = rz;
|
this->redline_z_ = rz;
|
||||||
this->hi_ = limit_ + rz;
|
this->hi_ = limit_ + rz;
|
||||||
|
#else
|
||||||
|
this->hi_ = limit_;
|
||||||
|
#endif
|
||||||
this->debug_flag_ = debug_flag;
|
this->debug_flag_ = debug_flag;
|
||||||
|
|
||||||
if (!lo_) {
|
if (!lo_) {
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
throw std::runtime_error(tostr("ArenaAlloc: allocation failed",
|
throw std::runtime_error(tostr("ArenaAlloc: allocation failed",
|
||||||
xtag("size", rz + z)));
|
xtag("size", rz + z)));
|
||||||
|
#else
|
||||||
|
throw std::runtime_error(tostr("ArenaAlloc: allocation failed",
|
||||||
|
xtag("size", z)));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,15 +56,25 @@ namespace xo {
|
||||||
this->checkpoint_ = nullptr;
|
this->checkpoint_ = nullptr;
|
||||||
this->free_ptr_ = nullptr;
|
this->free_ptr_ = nullptr;
|
||||||
this->limit_ = nullptr;
|
this->limit_ = nullptr;
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
this->redline_z_ = 0;
|
this->redline_z_ = 0;
|
||||||
|
#endif
|
||||||
this->hi_ = nullptr;
|
this->hi_ = nullptr;
|
||||||
this->debug_flag_ = false;
|
this->debug_flag_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
up<ArenaAlloc>
|
up<ArenaAlloc>
|
||||||
ArenaAlloc::make(const std::string & name, std::size_t rz, std::size_t z, bool debug_flag)
|
ArenaAlloc::make(const std::string & name,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
|
std::size_t rz,
|
||||||
|
#endif
|
||||||
|
std::size_t z, bool debug_flag)
|
||||||
{
|
{
|
||||||
return up<ArenaAlloc>(new ArenaAlloc(name, rz, z, debug_flag));
|
return up<ArenaAlloc>(new ArenaAlloc(name,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
|
rz,
|
||||||
|
#endif
|
||||||
|
z, debug_flag));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -144,7 +171,11 @@ namespace xo {
|
||||||
ArenaAlloc::clear()
|
ArenaAlloc::clear()
|
||||||
{
|
{
|
||||||
this->set_free_ptr(lo_);
|
this->set_free_ptr(lo_);
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
this->limit_ = hi_ - redline_z_;
|
this->limit_ = hi_ - redline_z_;
|
||||||
|
#else
|
||||||
|
this->limit_ = hi_;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -184,10 +215,12 @@ namespace xo {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
void
|
void
|
||||||
ArenaAlloc::release_redline_memory() {
|
ArenaAlloc::release_redline_memory() {
|
||||||
this->limit_ = this->hi_;
|
this->limit_ = this->hi_;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} /*namespace gc*/
|
} /*namespace gc*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
|
||||||
|
|
@ -255,13 +255,17 @@ namespace xo {
|
||||||
std::byte * x = nursery_[role2int(role::to_space)]->alloc(z);
|
std::byte * x = nursery_[role2int(role::to_space)]->alloc(z);
|
||||||
|
|
||||||
if (!x) {
|
if (!x) {
|
||||||
|
/* ListAlloc won't fail -- instead will increase heap size */
|
||||||
|
|
||||||
this->request_gc(generation::nursery);
|
this->request_gc(generation::nursery);
|
||||||
|
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
if (incr_gc_pending_ || full_gc_pending_)
|
if (incr_gc_pending_ || full_gc_pending_)
|
||||||
nursery_[role2int(role::to_space)]->release_redline_memory();
|
nursery_[role2int(role::to_space)]->release_redline_memory();
|
||||||
|
|
||||||
/* try (just once) more, maybe request fits in redline space */
|
/* try (just once) more, maybe request fits in redline space */
|
||||||
x = nursery_[role2int(role::to_space)]->alloc(z);
|
x = nursery_[role2int(role::to_space)]->alloc(z);
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(x);
|
assert(x);
|
||||||
}
|
}
|
||||||
|
|
@ -310,7 +314,9 @@ namespace xo {
|
||||||
|
|
||||||
this->request_gc(generation::nursery);
|
this->request_gc(generation::nursery);
|
||||||
|
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
nursery_[role2int(role::to_space)]->release_redline_memory();
|
nursery_[role2int(role::to_space)]->release_redline_memory();
|
||||||
|
#endif
|
||||||
|
|
||||||
retval = nursery_[role2int(role::to_space)]->alloc(z);
|
retval = nursery_[role2int(role::to_space)]->alloc(z);
|
||||||
}
|
}
|
||||||
|
|
@ -387,11 +393,13 @@ namespace xo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
void
|
void
|
||||||
GC::release_redline_memory()
|
GC::release_redline_memory()
|
||||||
{
|
{
|
||||||
// not supported feature for GC
|
// not supported feature for GC
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
GC::swap_nursery()
|
GC::swap_nursery()
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ namespace xo {
|
||||||
ListAlloc::ListAlloc(std::unique_ptr<ArenaAlloc> hd,
|
ListAlloc::ListAlloc(std::unique_ptr<ArenaAlloc> hd,
|
||||||
ArenaAlloc * marked,
|
ArenaAlloc * marked,
|
||||||
std::size_t cz, std::size_t nz, std::size_t tz,
|
std::size_t cz, std::size_t nz, std::size_t tz,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
bool use_redline,
|
bool use_redline,
|
||||||
|
#endif
|
||||||
bool debug_flag)
|
bool debug_flag)
|
||||||
: start_z_{cz},
|
: start_z_{cz},
|
||||||
hd_{std::move(hd)},
|
hd_{std::move(hd)},
|
||||||
|
|
@ -22,7 +24,9 @@ namespace xo {
|
||||||
current_z_{cz},
|
current_z_{cz},
|
||||||
next_z_{nz},
|
next_z_{nz},
|
||||||
total_z_{tz},
|
total_z_{tz},
|
||||||
|
#ifdef REDLINE_MEMOORY
|
||||||
use_redline_{use_redline},
|
use_redline_{use_redline},
|
||||||
|
#endif
|
||||||
debug_flag_{debug_flag}
|
debug_flag_{debug_flag}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
@ -34,7 +38,11 @@ namespace xo {
|
||||||
up<ListAlloc>
|
up<ListAlloc>
|
||||||
ListAlloc::make(const std::string & name, std::size_t cz, std::size_t nz, bool debug_flag)
|
ListAlloc::make(const std::string & name, std::size_t cz, std::size_t nz, bool debug_flag)
|
||||||
{
|
{
|
||||||
std::unique_ptr<ArenaAlloc> hd{ArenaAlloc::make(name, 0, cz, debug_flag)};
|
std::unique_ptr<ArenaAlloc> hd{ArenaAlloc::make(name,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
|
cz, debug_flag)};
|
||||||
|
|
||||||
if (!hd)
|
if (!hd)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -44,7 +52,9 @@ namespace xo {
|
||||||
up<ListAlloc> retval{new ListAlloc(std::move(hd),
|
up<ListAlloc> retval{new ListAlloc(std::move(hd),
|
||||||
marked,
|
marked,
|
||||||
cz, nz, cz,
|
cz, nz, cz,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
false /*!use_redline*/,
|
false /*!use_redline*/,
|
||||||
|
#endif
|
||||||
debug_flag)};
|
debug_flag)};
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -248,20 +258,26 @@ namespace xo {
|
||||||
current_z_ = 0;
|
current_z_ = 0;
|
||||||
next_z_ = 0;
|
next_z_ = 0;
|
||||||
total_z_ = 0;
|
total_z_ = 0;
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
use_redline_ = false;
|
use_redline_ = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ListAlloc::reset(std::size_t z)
|
ListAlloc::reset(std::size_t z)
|
||||||
{
|
{
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
// warning: hd_->size() does not include redline memory
|
// warning: hd_->size() does not include redline memory
|
||||||
hd_->release_redline_memory();
|
hd_->release_redline_memory();
|
||||||
|
#endif
|
||||||
|
|
||||||
bool recycle_head_bucket = hd_ && (z <= hd_->size());
|
bool recycle_head_bucket = hd_ && (z <= hd_->size());
|
||||||
|
|
||||||
this->full_l_.clear();
|
this->full_l_.clear();
|
||||||
this->marked_ = nullptr;
|
this->marked_ = nullptr;
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
this->redlined_flag_ = false;
|
this->redlined_flag_ = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (recycle_head_bucket) {
|
if (recycle_head_bucket) {
|
||||||
this->hd_->clear();
|
this->hd_->clear();
|
||||||
|
|
@ -291,7 +307,11 @@ namespace xo {
|
||||||
|
|
||||||
std::string name = hd_->name() + "+exp";
|
std::string name = hd_->name() + "+exp";
|
||||||
|
|
||||||
std::unique_ptr<ArenaAlloc> new_alloc = ArenaAlloc::make(name, 0, cz, debug_flag_);
|
std::unique_ptr<ArenaAlloc> new_alloc = ArenaAlloc::make(name,
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
|
cz, debug_flag_);
|
||||||
|
|
||||||
if (!new_alloc)
|
if (!new_alloc)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -325,6 +345,7 @@ namespace xo {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
void
|
void
|
||||||
ListAlloc::release_redline_memory()
|
ListAlloc::release_redline_memory()
|
||||||
{
|
{
|
||||||
|
|
@ -333,6 +354,7 @@ namespace xo {
|
||||||
|
|
||||||
this->hd_->release_redline_memory();
|
this->hd_->release_redline_memory();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} /*namespace gc*/
|
} /*namespace gc*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,15 @@ namespace xo {
|
||||||
namespace {
|
namespace {
|
||||||
struct testcase_alloc {
|
struct testcase_alloc {
|
||||||
testcase_alloc(std::size_t rz, std::size_t z)
|
testcase_alloc(std::size_t rz, std::size_t z)
|
||||||
: redline_z_{rz}, arena_z_{z} {}
|
:
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
|
redline_z_{rz},
|
||||||
|
#endif
|
||||||
|
arena_z_{z} {}
|
||||||
|
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
std::size_t redline_z_;
|
std::size_t redline_z_;
|
||||||
|
#endif
|
||||||
std::size_t arena_z_;
|
std::size_t arena_z_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -35,7 +41,11 @@ namespace xo {
|
||||||
|
|
||||||
constexpr bool c_debug_flag = false;
|
constexpr bool c_debug_flag = false;
|
||||||
|
|
||||||
auto alloc = ArenaAlloc::make("linearalloc", tc.redline_z_, tc.arena_z_, c_debug_flag);
|
auto alloc = ArenaAlloc::make("linearalloc",
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
|
tc.redline_z_,
|
||||||
|
#endif
|
||||||
|
tc.arena_z_, c_debug_flag);
|
||||||
|
|
||||||
REQUIRE(alloc.get());
|
REQUIRE(alloc.get());
|
||||||
REQUIRE(alloc->name() == "linearalloc");
|
REQUIRE(alloc->name() == "linearalloc");
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,11 @@ namespace xo {
|
||||||
TEST_CASE("String.append", "[String]")
|
TEST_CASE("String.append", "[String]")
|
||||||
{
|
{
|
||||||
const bool c_debug_flag = false;
|
const bool c_debug_flag = false;
|
||||||
up<ArenaAlloc> arena = ArenaAlloc::make("testarena", 0, 16*1024, c_debug_flag);
|
up<ArenaAlloc> arena = ArenaAlloc::make("testarena",
|
||||||
|
#ifdef REDLINE_MEMORY
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
|
16*1024, c_debug_flag);
|
||||||
|
|
||||||
Object::mm = arena.get();
|
Object::mm = arena.get();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue