pretty gc up a bit

This commit is contained in:
2023-12-27 12:46:02 +01:00
parent f6a59c85e8
commit e986daf6a6
2 changed files with 89 additions and 99 deletions

View File

@@ -133,7 +133,7 @@ private:
{
std::lock_guard tmplg(_new_roots_lock);
Handle ret(cell);
_temp_cells.emplace(cell);
_temp_cells.emplace_back(cell);
if ((_cells_num + _temp_cells.size() + 1) >= (size_t) (_cell_limit / 2)) {
request_gc();
}
@@ -145,10 +145,9 @@ private:
void add_root(Cell *c);
void remove_root(Cell *c);
std::mutex _cells_lock;
std::set<Cell *> _cells;
std::list<Cell *> _cells;
std::atomic<size_t> _cells_num = 0;
std::set<Cell *> _temp_cells;
std::list<Cell *> _temp_cells;
std::mutex _indexes_lock;
std::unordered_map<CellValType, Cell *> _numatom_index;

View File

@@ -55,8 +55,8 @@ void MemoryContext::gc_thread_entry() {
if (_gc_thread_stop) return;
std::cerr << "gc start " << '\n';
auto gcstart = std::chrono::high_resolution_clock::now();
std::unordered_set<Cell *> seenroots;
std::queue<Cell *> toVisit;
auto visitAll = [&]() {
@@ -65,12 +65,9 @@ void MemoryContext::gc_thread_entry() {
toVisit.pop();
if (c == nullptr) continue;
if (!_cells.contains(c)) _cells.emplace(c);
if (c->live) continue;
c->live = true;
// std::cerr << "processing c " << c << " " << static_cast<int>(c->_type) << "\n";
if (c->_type == CellType::CONS) {
@@ -86,116 +83,110 @@ void MemoryContext::gc_thread_entry() {
};
{
std::lock_guard cl(_cells_lock);
auto start = std::chrono::high_resolution_clock::now();
decltype(_new_roots) new_roots;
{
decltype(_new_roots) new_roots;
decltype(_temp_cells) temp_cells;
{
decltype(_temp_cells) temp_cells;
{
std::lock_guard l(_new_roots_lock);
std::swap(new_roots, _new_roots);
std::swap(temp_cells, _temp_cells);
}
_cells.insert(temp_cells.begin(), temp_cells.end());
}
for (auto const &r: new_roots) {
// std::cerr << "processing new " << r.first << " diff " << r.second << "\n";
if (r.second == 0) continue;
_roots[r.first] += r.second;
if (_roots[r.first] <= 0)
_roots.erase(r.first);
std::lock_guard l(_new_roots_lock);
std::swap(new_roots, _new_roots);
std::swap(temp_cells, _temp_cells);
}
_cells.splice(_cells.end(), temp_cells);
}
for (auto const &r: new_roots) {
// std::cerr << "processing new " << r.first << " diff " << r.second << "\n";
if (r.second == 0) continue;
_roots[r.first] += r.second;
if (_roots[r.first] <= 0)
_roots.erase(r.first);
}
auto stop = std::chrono::high_resolution_clock::now();
std::cerr << "New roots time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
}
assert(std::none_of(_cells.begin(), _cells.end(), [](const auto &p) { return p->live.load(); }));
{
auto start = std::chrono::high_resolution_clock::now();
std::for_each(_cells.begin(), _cells.end(), [&](Cell *c) {
c->live = false;
});
start = std::chrono::high_resolution_clock::now();
for (const auto &r: _roots) {
// std::cerr << "processing r " << r.first << " diff " << r.second << "\n";
seenroots.emplace(r.first);
toVisit.emplace(r.first);
}
visitAll();
stop = std::chrono::high_resolution_clock::now();
auto stop = std::chrono::high_resolution_clock::now();
// std::cerr << "Scanned " << _roots.size() << " roots" << std::endl;
std::cerr << "Roots scan time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
}
{
decltype(_gc_dirty_notif_queue) dirtied;
std::unique_lock dql(_gc_dirty_notif_queue_lock);
{
auto start = std::chrono::high_resolution_clock::now();
decltype(_gc_dirty_notif_queue) dirtied;
std::unique_lock dql(_gc_dirty_notif_queue_lock);
std::swap(dirtied, _gc_dirty_notif_queue);
while (!dirtied.empty()) {
dql.unlock();
for (const auto &r: dirtied) {
// std::cerr << "processing dirty " << r << "\n";
toVisit.emplace(r);
}
visitAll();
dirtied = {};
dql.lock();
std::swap(dirtied, _gc_dirty_notif_queue);
start = std::chrono::high_resolution_clock::now();
while (!dirtied.empty()) {
dql.unlock();
for (const auto &r: dirtied) {
// std::cerr << "processing dirty " << r << "\n";
if (seenroots.contains(r)) continue;
seenroots.emplace(r);
toVisit.emplace(r);
}
visitAll();
dirtied = {};
dql.lock();
std::swap(dirtied, _gc_dirty_notif_queue);
}
stop = std::chrono::high_resolution_clock::now();
std::cerr << "Dirty mark time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
assert(dql.owns_lock());
uint64_t freed = 0;
start = std::chrono::high_resolution_clock::now();
std::vector<Cell *> toremove;
for (const auto &l: _cells) {
if (!l->live) {
freed += 1;
if (l->_type == CellType::NUMATOM) {
std::lock_guard il(_indexes_lock);
// std::cerr << "deleting num: " << l << "\n";
_numatom_index.erase(dynamic_cast<NumAtomCell &>(*l)._val);
} else if (l->_type == CellType::STRATOM) {
std::lock_guard il(_indexes_lock);
// std::cerr << "deleting str: " << l << "\n";
_stratom_index.erase(dynamic_cast<StrAtomCell &>(*l)._val);
}
assert(!_roots.contains(l));
// std::cerr << "deleting: " << l << "\n";
toremove.emplace_back(l);
delete l;
} else {
// std::cerr << "resetting num: " << l << "\n";
l->live = false;
}
}
for (const auto &l: toremove) {
_cells.erase(l);
}
stop = std::chrono::high_resolution_clock::now();
std::cerr << "Sweep time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
_cells_num = _cells.size();
std::cerr << "GC Freed " << freed << " cells left: " << _cells_num << " \n";
}
{
std::unique_lock l(_gc_done_m);
std::unique_lock l2(_gc_request_m);
_gc_done = true;
_gc_request = false;
_gc_done_cv.notify_all();
}
auto stop = std::chrono::high_resolution_clock::now();
std::cerr << "Dirty mark time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
}
{
auto start = std::chrono::high_resolution_clock::now();
uint64_t freed = 0;
_cells.remove_if([&](Cell *l) {
if (!l->live) {
freed += 1;
if (l->_type == CellType::NUMATOM) {
std::lock_guard il(_indexes_lock);
// std::cerr << "deleting num: " << l << "\n";
_numatom_index.erase(dynamic_cast<NumAtomCell &>(*l)._val);
} else if (l->_type == CellType::STRATOM) {
std::lock_guard il(_indexes_lock);
// std::cerr << "deleting str: " << l << "\n";
_stratom_index.erase(dynamic_cast<StrAtomCell &>(*l)._val);
}
delete l;
return true;
}
return false;
});
auto stop = std::chrono::high_resolution_clock::now();
std::cerr << "Sweep time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
_cells_num = _cells.size();
std::cerr << "GC Freed " << freed << " cells left: " << _cells_num << " \n";
}
auto gcstop = std::chrono::high_resolution_clock::now();
std::cerr << "GC total time: " << std::chrono::duration_cast<std::chrono::microseconds>(gcstop - gcstart).count() << "\n";
{
std::unique_lock l(_gc_done_m);
std::unique_lock l2(_gc_request_m);
_gc_done = true;
_gc_request = false;
_gc_done_cv.notify_all();
}
}
}