GC: change collection trigger (#108)

This commit is contained in:
mihacooper 2018-10-02 16:18:03 +03:00 committed by Ilia
parent 3366aae6f2
commit e313e58ea3
3 changed files with 82 additions and 12 deletions

View File

@ -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;
};

View File

@ -17,8 +17,8 @@ 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_)
collect();
if (enabled_ && count() >= step_ * lastCleanup_)
collect();
std::unique_ptr<ViewType> object(new ViewType(std::forward<Args>(args)...));
auto copy = *object;
@ -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;
};

View File

@ -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