GC: change collection trigger (#108)
This commit is contained in:
parent
3366aae6f2
commit
e313e58ea3
@ -7,10 +7,12 @@
|
||||
|
||||
namespace effil {
|
||||
|
||||
constexpr size_t MINIMUN_SIZE_LEFT = 100;
|
||||
|
||||
GC::GC()
|
||||
: enabled_(true)
|
||||
, lastCleanup_(0)
|
||||
, step_(200) {}
|
||||
, lastCleanup_(MINIMUN_SIZE_LEFT)
|
||||
, step_(2.) {}
|
||||
|
||||
// Here is the naive tri-color marking
|
||||
// garbage collecting algorithm implementation.
|
||||
@ -41,7 +43,7 @@ void GC::collect() {
|
||||
DEBUG << "Removing " << (objects_.size() - black.size()) << " out of " << objects_.size() << std::endl;
|
||||
objects_ = std::move(black);
|
||||
|
||||
lastCleanup_.store(0);
|
||||
lastCleanup_.store(std::max(objects_.size(), MINIMUN_SIZE_LEFT));
|
||||
}
|
||||
|
||||
size_t GC::count() const {
|
||||
@ -63,9 +65,13 @@ sol::table GC::exportAPI(sol::state_view& lua) {
|
||||
api["step"] = [](const sol::stack_object& newStep){
|
||||
auto previous = instance().step();
|
||||
if (newStep.valid()) {
|
||||
REQUIRE(newStep.get_type() == sol::type::number) << "bad argument #1 to 'effil.gc.step' (number expected, got " << luaTypename(newStep) << ")";
|
||||
REQUIRE(newStep.as<int>() >= 0) << "effil.gc.step: invalid capacity value = " << newStep.as<int>();
|
||||
instance().step(newStep.as<size_t>());
|
||||
REQUIRE(newStep.get_type() == sol::type::number)
|
||||
<< "bad argument #1 to 'effil.gc.step' (number expected, got "
|
||||
<< luaTypename(newStep) << ")";
|
||||
REQUIRE(newStep.as<double>() > 1)
|
||||
<< "effil.gc.step: invalid capacity value = "
|
||||
<< newStep.as<double>();
|
||||
instance().step(newStep.as<double>());
|
||||
}
|
||||
return previous;
|
||||
};
|
||||
|
||||
@ -17,7 +17,7 @@ public:
|
||||
// This method is used to create all managed objects.
|
||||
template <typename ViewType, typename... Args>
|
||||
ViewType create(Args&&... args) {
|
||||
if (enabled_ && lastCleanup_.fetch_add(1) == step_)
|
||||
if (enabled_ && count() >= step_ * lastCleanup_)
|
||||
collect();
|
||||
|
||||
std::unique_ptr<ViewType> object(new ViewType(std::forward<Args>(args)...));
|
||||
@ -43,8 +43,8 @@ public:
|
||||
private:
|
||||
mutable std::mutex lock_;
|
||||
bool enabled_;
|
||||
std::atomic<size_t> lastCleanup_;
|
||||
size_t step_;
|
||||
std::atomic<uint64_t> lastCleanup_;
|
||||
double step_;
|
||||
std::unordered_map<GCHandle, std::unique_ptr<BaseGCObject>> objects_;
|
||||
|
||||
private:
|
||||
@ -55,8 +55,8 @@ private:
|
||||
void collect();
|
||||
void pause() { enabled_ = false; }
|
||||
void resume() { enabled_ = true; }
|
||||
size_t step() const { return step_; }
|
||||
void step(size_t newStep) { step_ = newStep; }
|
||||
double step() const { return step_; }
|
||||
void step(double newStep) { step_ = newStep; }
|
||||
bool enabled() { return enabled_; }
|
||||
size_t count() const;
|
||||
};
|
||||
|
||||
@ -55,3 +55,67 @@ test.gc.store_same_value = function()
|
||||
effil.gc.collect()
|
||||
c:pop()[1] = 0
|
||||
end
|
||||
|
||||
local function create_fabric()
|
||||
local f = { data = {} }
|
||||
|
||||
function f:create(num)
|
||||
for i = 1, num do
|
||||
table.insert(self.data, effil.table())
|
||||
end
|
||||
end
|
||||
|
||||
function f:remove(num)
|
||||
for i = 1, num do
|
||||
table.remove(self.data, 1)
|
||||
end
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
test.gc.check_iterative = function()
|
||||
test.equal(gc.count(), 1)
|
||||
local fabric = create_fabric()
|
||||
test.equal(2, effil.gc.step())
|
||||
|
||||
fabric:create(199)
|
||||
test.equal(gc.count(), 200)
|
||||
|
||||
fabric:remove(50)
|
||||
collectgarbage()
|
||||
test.equal(gc.count(), 200)
|
||||
|
||||
fabric:create(1) -- trigger GC
|
||||
test.equal(gc.count(), 151)
|
||||
fabric:remove(150)
|
||||
|
||||
fabric:create(149)
|
||||
test.equal(gc.count(), 300)
|
||||
collectgarbage()
|
||||
|
||||
fabric:create(1) -- trigger GC
|
||||
test.equal(gc.count(), 151)
|
||||
end
|
||||
|
||||
test.gc.check_step = function()
|
||||
local fabric = create_fabric()
|
||||
effil.gc.step(3)
|
||||
|
||||
fabric:create(299)
|
||||
fabric:remove(100)
|
||||
test.equal(gc.count(), 300)
|
||||
collectgarbage()
|
||||
|
||||
fabric:create(1) -- trigger GC
|
||||
test.equal(gc.count(), 201)
|
||||
|
||||
test.equal(3, effil.gc.step(2.5))
|
||||
|
||||
fabric:create(299)
|
||||
fabric:remove(250)
|
||||
test.equal(gc.count(), 500)
|
||||
collectgarbage()
|
||||
|
||||
fabric:create(1) -- trigger GC
|
||||
test.equal(gc.count(), 251)
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user