/** * Insert a formatted representation of the %arena onto the output stream 'o'. */ void Arena::insert(std::ostream& o) const { /* Recurse through the list of arenas that runs through the parent attribute, building up a name of the form 'root/.../parent-arena/arena' in the string from which we inherit. Note that this list is short - no more than a dozen links, at most - and that each recursive call pushes just two pointers on the stack, so the consumption of stack space is minimal...*/ struct pathname : std::string { void traverse(const Arena& arena) // Build up the name { if (ArenaPtr p = arena.parent()) // Has a parent arena? { traverse(*p); // ...traverse parent *this += '/'; // ...add a delimiter } *this += arena.name(); // Append arena name } pathname(const Arena& arena) {traverse(arena);} // Traverse ancestors }; o << "name=\"" << pathname(*this) << '"' // Emit path name << ",available=" << bytes_t (available()) // Emit available() << ",allocated=" << bytes_t (allocated()) // Emit allocated() << ",peakusage=" << bytes_t (peakusage()) // Emit peakusage() << ",allocations=" << size_t (allocations()); // Emit allocations() }
void MemoryAllocatorTrace::exit (void) { check_allocations(); _alloc_recording = false; LOG_MESSAGE << "---- MEMORY DUMP -------------------------------------------------------------"; LOG_MESSAGE << "Total Allocations: " << _total_allocs << " bytes (" << _total_allocs/(1024.0F*1024.0F) << " MB)"; LOG_MESSAGE << "Peak Allocations: " << _peak_allocs << " bytes (" << _peak_allocs/(1024.0F*1024.0F) << " MB)"; LOG_MESSAGE << "Current Allocations: " << _current_allocs << " bytes (" << _current_allocs/(1024.0F*1024.0F) << " MB)"; // // Named objects // std::multimap<char *, Allocation*, std::less<char *>> grouped; LOG_MESSAGE << "Named objects leaked: "; FOR_EACH (i,allocations()) { if (i->second._name) { grouped.insert(std::make_pair(i->second._name, &(i->second))); } } for (auto grouped_i = grouped.begin(); grouped_i != grouped.end(); grouped_i = grouped.upper_bound(grouped_i->first) ) { auto lower = grouped.lower_bound(grouped_i->first); auto upper = grouped.upper_bound(grouped_i->first); DTuint count = 0; DTsize size = 0; for (auto grouped_j = lower; grouped_j != upper; ++grouped_j) { ++count; size += grouped_j->second->_size; } LOG_MESSAGE << " Kind " << grouped_i->first << " Num " << count << " Total Size: " << size; } // // Unnamed objects // LOG_MESSAGE << "Unnamed objects leaked: "; std::multimap<DTuint, Allocation*, std::greater<DTuint>> ordered; FOR_EACH (i,allocations()) { if (!i->second._name) { ordered.insert(std::make_pair(i->second._size, &(i->second))); } } for (auto ordered_i = ordered.begin(); ordered_i != ordered.end(); ordered_i = ordered.upper_bound(ordered_i->first) ) { auto lower = ordered.lower_bound(ordered_i->first); auto upper = ordered.upper_bound(ordered_i->first); DTuint count = 0; for (auto ordered_j = lower; ordered_j != upper; ++ordered_j) { ++count; } LOG_MESSAGE << " Num bytes " << ordered_i->first << " Num " << count; } }