mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 04:27:40 +00:00
LibJS: Add API for doing GC with a little debug log report at end
You can now pass print_report=true to Heap::collect_garbage() and it will print out a little summary of the time spent, and counts of live vs freed cells and blocks.
This commit is contained in:
parent
6444f49d22
commit
bbd3192535
2 changed files with 31 additions and 5 deletions
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include <AK/Badge.h>
|
#include <AK/Badge.h>
|
||||||
#include <AK/HashTable.h>
|
#include <AK/HashTable.h>
|
||||||
|
#include <LibCore/ElapsedTimer.h>
|
||||||
#include <LibJS/Heap/Handle.h>
|
#include <LibJS/Heap/Handle.h>
|
||||||
#include <LibJS/Heap/Heap.h>
|
#include <LibJS/Heap/Heap.h>
|
||||||
#include <LibJS/Heap/HeapBlock.h>
|
#include <LibJS/Heap/HeapBlock.h>
|
||||||
|
@ -82,8 +83,10 @@ Cell* Heap::allocate_cell(size_t size)
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heap::collect_garbage(CollectionType collection_type)
|
void Heap::collect_garbage(CollectionType collection_type, bool print_report)
|
||||||
{
|
{
|
||||||
|
Core::ElapsedTimer collection_measurement_timer;
|
||||||
|
collection_measurement_timer.start();
|
||||||
if (collection_type == CollectionType::CollectGarbage) {
|
if (collection_type == CollectionType::CollectGarbage) {
|
||||||
if (m_gc_deferrals) {
|
if (m_gc_deferrals) {
|
||||||
m_should_gc_when_deferral_ends = true;
|
m_should_gc_when_deferral_ends = true;
|
||||||
|
@ -93,7 +96,7 @@ void Heap::collect_garbage(CollectionType collection_type)
|
||||||
gather_roots(roots);
|
gather_roots(roots);
|
||||||
mark_live_cells(roots);
|
mark_live_cells(roots);
|
||||||
}
|
}
|
||||||
sweep_dead_cells();
|
sweep_dead_cells(print_report, collection_measurement_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heap::gather_roots(HashTable<Cell*>& roots)
|
void Heap::gather_roots(HashTable<Cell*>& roots)
|
||||||
|
@ -230,13 +233,18 @@ void Heap::mark_live_cells(const HashTable<Cell*>& roots)
|
||||||
visitor.visit(root);
|
visitor.visit(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heap::sweep_dead_cells()
|
void Heap::sweep_dead_cells(bool print_report, const Core::ElapsedTimer& measurement_timer)
|
||||||
{
|
{
|
||||||
#ifdef HEAP_DEBUG
|
#ifdef HEAP_DEBUG
|
||||||
dbg() << "sweep_dead_cells:";
|
dbg() << "sweep_dead_cells:";
|
||||||
#endif
|
#endif
|
||||||
Vector<HeapBlock*, 32> empty_blocks;
|
Vector<HeapBlock*, 32> empty_blocks;
|
||||||
|
|
||||||
|
size_t collected_cells = 0;
|
||||||
|
size_t live_cells = 0;
|
||||||
|
size_t collected_cell_bytes = 0;
|
||||||
|
size_t live_cell_bytes = 0;
|
||||||
|
|
||||||
for (auto& block : m_blocks) {
|
for (auto& block : m_blocks) {
|
||||||
bool block_has_live_cells = false;
|
bool block_has_live_cells = false;
|
||||||
block->for_each_cell([&](Cell* cell) {
|
block->for_each_cell([&](Cell* cell) {
|
||||||
|
@ -246,9 +254,13 @@ void Heap::sweep_dead_cells()
|
||||||
dbg() << " ~ " << cell;
|
dbg() << " ~ " << cell;
|
||||||
#endif
|
#endif
|
||||||
block->deallocate(cell);
|
block->deallocate(cell);
|
||||||
|
++collected_cells;
|
||||||
|
collected_cell_bytes += block->cell_size();
|
||||||
} else {
|
} else {
|
||||||
cell->set_marked(false);
|
cell->set_marked(false);
|
||||||
block_has_live_cells = true;
|
block_has_live_cells = true;
|
||||||
|
++live_cells;
|
||||||
|
live_cell_bytes += block->cell_size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -268,6 +280,19 @@ void Heap::sweep_dead_cells()
|
||||||
dbg() << " > Live HeapBlock @ " << block << ": cell_size=" << block->cell_size();
|
dbg() << " > Live HeapBlock @ " << block << ": cell_size=" << block->cell_size();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int time_spent = measurement_timer.elapsed();
|
||||||
|
|
||||||
|
if (print_report) {
|
||||||
|
dbg() << "Garbage collection report";
|
||||||
|
dbg() << "=============================================";
|
||||||
|
dbg() << " Time spent: " << time_spent << " ms";
|
||||||
|
dbg() << " Live cells: " << live_cells << " (" << live_cell_bytes << " bytes)";
|
||||||
|
dbg() << "Collected cells: " << collected_cells << " (" << collected_cell_bytes << " bytes)";
|
||||||
|
dbg() << " Live blocks: " << m_blocks.size() << " (" << m_blocks.size() * HeapBlock::block_size << " bytes)";
|
||||||
|
dbg() << " Freed blocks: " << empty_blocks.size() << " (" << empty_blocks.size() * HeapBlock::block_size << " bytes)";
|
||||||
|
dbg() << "=============================================";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heap::did_create_handle(Badge<HandleImpl>, HandleImpl& impl)
|
void Heap::did_create_handle(Badge<HandleImpl>, HandleImpl& impl)
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <AK/NonnullOwnPtr.h>
|
#include <AK/NonnullOwnPtr.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibCore/Forward.h>
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
#include <LibJS/Heap/Handle.h>
|
#include <LibJS/Heap/Handle.h>
|
||||||
#include <LibJS/Runtime/Cell.h>
|
#include <LibJS/Runtime/Cell.h>
|
||||||
|
@ -68,7 +69,7 @@ public:
|
||||||
CollectEverything,
|
CollectEverything,
|
||||||
};
|
};
|
||||||
|
|
||||||
void collect_garbage(CollectionType = CollectionType::CollectGarbage);
|
void collect_garbage(CollectionType = CollectionType::CollectGarbage, bool print_report = false);
|
||||||
|
|
||||||
Interpreter& interpreter() { return m_interpreter; }
|
Interpreter& interpreter() { return m_interpreter; }
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ private:
|
||||||
void gather_roots(HashTable<Cell*>&);
|
void gather_roots(HashTable<Cell*>&);
|
||||||
void gather_conservative_roots(HashTable<Cell*>&);
|
void gather_conservative_roots(HashTable<Cell*>&);
|
||||||
void mark_live_cells(const HashTable<Cell*>& live_cells);
|
void mark_live_cells(const HashTable<Cell*>& live_cells);
|
||||||
void sweep_dead_cells();
|
void sweep_dead_cells(bool print_report, const Core::ElapsedTimer&);
|
||||||
|
|
||||||
Cell* cell_from_possible_pointer(FlatPtr);
|
Cell* cell_from_possible_pointer(FlatPtr);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue