diff --git a/Libraries/LibJS/Heap/Heap.cpp b/Libraries/LibJS/Heap/Heap.cpp index 805e385297..75b8b75fae 100644 --- a/Libraries/LibJS/Heap/Heap.cpp +++ b/Libraries/LibJS/Heap/Heap.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -82,8 +83,10 @@ Cell* Heap::allocate_cell(size_t size) 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 (m_gc_deferrals) { m_should_gc_when_deferral_ends = true; @@ -93,7 +96,7 @@ void Heap::collect_garbage(CollectionType collection_type) gather_roots(roots); mark_live_cells(roots); } - sweep_dead_cells(); + sweep_dead_cells(print_report, collection_measurement_timer); } void Heap::gather_roots(HashTable& roots) @@ -230,13 +233,18 @@ void Heap::mark_live_cells(const HashTable& roots) visitor.visit(root); } -void Heap::sweep_dead_cells() +void Heap::sweep_dead_cells(bool print_report, const Core::ElapsedTimer& measurement_timer) { #ifdef HEAP_DEBUG dbg() << "sweep_dead_cells:"; #endif Vector 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) { bool block_has_live_cells = false; block->for_each_cell([&](Cell* cell) { @@ -246,9 +254,13 @@ void Heap::sweep_dead_cells() dbg() << " ~ " << cell; #endif block->deallocate(cell); + ++collected_cells; + collected_cell_bytes += block->cell_size(); } else { cell->set_marked(false); 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(); } #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& impl) diff --git a/Libraries/LibJS/Heap/Heap.h b/Libraries/LibJS/Heap/Heap.h index 064c18caeb..75aebb5860 100644 --- a/Libraries/LibJS/Heap/Heap.h +++ b/Libraries/LibJS/Heap/Heap.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,7 @@ public: CollectEverything, }; - void collect_garbage(CollectionType = CollectionType::CollectGarbage); + void collect_garbage(CollectionType = CollectionType::CollectGarbage, bool print_report = false); Interpreter& interpreter() { return m_interpreter; } @@ -90,7 +91,7 @@ private: void gather_roots(HashTable&); void gather_conservative_roots(HashTable&); void mark_live_cells(const HashTable& live_cells); - void sweep_dead_cells(); + void sweep_dead_cells(bool print_report, const Core::ElapsedTimer&); Cell* cell_from_possible_pointer(FlatPtr);