mmlr + bonefish:

* dump_allocations_per_caller(): Compute the total allocation count and
  size from the caller infos instead of using return arguments in the
  helper functions called.
* Move caller info update code from analyze_allocation_callers() to new
  function slab_debug_add_allocation_for_caller(), so it can be reused.
* Add MemoryManager::AnalyzeAllocationCallers() to collect the
  allocation information for the memory manager.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43078 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2011-11-01 19:40:27 +00:00
parent 244a545018
commit 0422a0f3ae
4 changed files with 115 additions and 53 deletions
+39 -4
View File
@@ -22,7 +22,6 @@
#include "kernel_debug_config.h"
#include "ObjectCache.h"
#include "slab_debug.h"
#include "slab_private.h"
@@ -867,6 +866,44 @@ MemoryManager::PerformMaintenance()
}
#if SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
/*static*/ bool
MemoryManager::AnalyzeAllocationCallers()
{
for (AreaTable::Iterator it = sAreaTable.GetIterator();
Area* area = it.Next();) {
for (int32 i = 0; i < SLAB_META_CHUNKS_PER_AREA; i++) {
MetaChunk* metaChunk = area->metaChunks + i;
if (metaChunk->chunkSize == 0)
continue;
for (uint32 k = 0; k < metaChunk->chunkCount; k++) {
Chunk* chunk = metaChunk->chunks + k;
// skip free chunks
if (_IsChunkFree(metaChunk, chunk))
continue;
addr_t reference = chunk->reference;
if ((reference & 1) == 0 || reference == 1)
continue;
addr_t chunkAddress = _ChunkAddress(metaChunk, chunk);
size_t size = reference - chunkAddress + 1;
slab_debug_add_allocation_for_caller(
_TrackingInfoFor((void*)chunkAddress, size), size);
}
}
}
return true;
}
#endif // SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
/*static*/ status_t
MemoryManager::_AllocateChunks(size_t chunkSize, uint32 chunkCount,
uint32 flags, MetaChunk*& _metaChunk, Chunk*& _chunk)
@@ -1989,9 +2026,7 @@ void
MemoryManager::_AddTrackingInfo(void* allocation, size_t size,
AbstractTraceEntryWithStackTrace* traceEntry)
{
AllocationTrackingInfo* info = (AllocationTrackingInfo*)
((uint8*)allocation + size - sizeof(AllocationTrackingInfo));
info->Init(traceEntry);
_TrackingInfoFor(allocation, size)->Init(traceEntry);
}
#endif // SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
+18 -3
View File
@@ -14,8 +14,7 @@
#include <util/DoublyLinkedList.h>
#include <util/OpenHashTable.h>
#include "kernel_debug_config.h"
#include "tracing_config.h"
#include "slab_debug.h"
class AbstractTraceEntryWithStackTrace;
@@ -61,6 +60,8 @@ public:
static bool MaintenanceNeeded();
static void PerformMaintenance();
static bool AnalyzeAllocationCallers();
private:
struct Tracing;
@@ -195,9 +196,11 @@ private:
static int _DumpArea(int argc, char** argv);
static int _DumpAreas(int argc, char** argv);
#if SLAB_ALLOCATION_TRACKING && SLAB_MEMORY_MANAGER_TRACING
#if SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
static void _AddTrackingInfo(void* allocation, size_t size,
AbstractTraceEntryWithStackTrace* entry);
static AllocationTrackingInfo* _TrackingInfoFor(void* allocation,
size_t size);
#endif
private:
@@ -273,4 +276,16 @@ MemoryManager::MetaChunk::GetArea() const
}
#if SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
/*static*/ inline AllocationTrackingInfo*
MemoryManager::_TrackingInfoFor(void* allocation, size_t size)
{
return (AllocationTrackingInfo*)((uint8*)allocation + size
- sizeof(AllocationTrackingInfo));
}
#endif // SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
#endif // MEMORY_MANAGER_H
+50 -41
View File
@@ -329,9 +329,6 @@ dump_cache_info(int argc, char* argv[])
#if SLAB_ALLOCATION_TRACKING_AVAILABLE
#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
// until memory manager tracking is analyzed
static caller_info*
get_caller_info(addr_t caller)
{
@@ -353,8 +350,6 @@ get_caller_info(addr_t caller)
return info;
}
#endif // SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
static int
caller_info_compare_size(const void* _a, const void* _b)
@@ -374,39 +369,47 @@ caller_info_compare_count(const void* _a, const void* _b)
}
bool
slab_debug_add_allocation_for_caller(const AllocationTrackingInfo* info,
size_t allocationSize)
{
if (!info->IsInitialized())
return true;
addr_t caller = 0;
AbstractTraceEntryWithStackTrace* traceEntry = info->TraceEntry();
if (traceEntry != NULL && info->IsTraceEntryValid()) {
caller = tracing_find_caller_in_stack_trace(
traceEntry->StackTrace(), kSlabCodeAddressRanges,
kSlabCodeAddressRangeCount);
}
caller_info* callerInfo = get_caller_info(caller);
if (callerInfo == NULL) {
kprintf("out of space for caller infos\n");
return false;
}
callerInfo->count++;
callerInfo->size += allocationSize;
return true;
}
#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
static bool
analyze_allocation_callers(ObjectCache* cache, const SlabList& slabList,
size_t& _totalAllocationSize, size_t& _totalAllocationCount)
analyze_allocation_callers(ObjectCache* cache, const SlabList& slabList)
{
for (SlabList::ConstIterator it = slabList.GetIterator();
slab* slab = it.Next();) {
for (uint32 i = 0; i < slab->size; i++) {
AllocationTrackingInfo* info = &slab->tracking[i];
if (!info->IsInitialized())
continue;
_totalAllocationSize += cache->object_size;
_totalAllocationCount++;
addr_t caller = 0;
AbstractTraceEntryWithStackTrace* traceEntry = info->TraceEntry();
if (traceEntry != NULL && info->IsTraceEntryValid()) {
caller = tracing_find_caller_in_stack_trace(
traceEntry->StackTrace(), kSlabCodeAddressRanges,
kSlabCodeAddressRangeCount);
}
caller_info* callerInfo = get_caller_info(caller);
if (callerInfo == NULL) {
kprintf("out of space for caller infos\n");
if (!slab_debug_add_allocation_for_caller(&slab->tracking[i],
cache->object_size)) {
return false;
}
callerInfo->count++;
callerInfo->size += cache->object_size;
}
}
@@ -415,13 +418,10 @@ analyze_allocation_callers(ObjectCache* cache, const SlabList& slabList,
static bool
analyze_allocation_callers(ObjectCache* cache, size_t& _totalAllocationSize,
size_t& _totalAllocationCount)
analyze_allocation_callers(ObjectCache* cache)
{
return analyze_allocation_callers(cache, cache->full, _totalAllocationSize,
_totalAllocationCount)
&& analyze_allocation_callers(cache, cache->partial,
_totalAllocationSize, _totalAllocationCount);
return analyze_allocation_callers(cache, cache->full)
&& analyze_allocation_callers(cache, cache->partial);
}
#endif // SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
@@ -453,12 +453,10 @@ dump_allocations_per_caller(int argc, char **argv)
sCallerInfoCount = 0;
size_t totalAllocationSize = 0;
size_t totalAllocationCount = 0;
if (cache != NULL) {
#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
analyze_allocation_callers(cache, totalAllocationSize,
totalAllocationCount);
if (!analyze_allocation_callers(cache))
return 0;
#else
kprintf("Object cache allocation tracking not available. "
"SLAB_OBJECT_CACHE_TRACING (%d) and "
@@ -471,10 +469,15 @@ dump_allocations_per_caller(int argc, char **argv)
ObjectCacheList::Iterator it = sObjectCaches.GetIterator();
while (it.HasNext()) {
analyze_allocation_callers(it.Next(), totalAllocationSize,
totalAllocationCount);
if (!analyze_allocation_callers(it.Next()))
return 0;
}
#endif
#if SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
if (!MemoryManager::AnalyzeAllocationCallers())
return 0;
#endif
}
// sort the array
@@ -484,6 +487,9 @@ dump_allocations_per_caller(int argc, char **argv)
kprintf("%ld different callers, sorted by %s...\n\n", sCallerInfoCount,
sortBySize ? "size" : "count");
size_t totalAllocationSize = 0;
size_t totalAllocationCount = 0;
kprintf(" count size caller\n");
kprintf("----------------------------------\n");
for (int32 i = 0; i < sCallerInfoCount; i++) {
@@ -503,6 +509,9 @@ dump_allocations_per_caller(int argc, char **argv)
exactMatch ? "" : " (nearest)");
} else
kprintf("\n");
totalAllocationCount += info.count;
totalAllocationSize += info.size;
}
kprintf("\ntotal allocations: %" B_PRIuSIZE ", %" B_PRIuSIZE " bytes\n",
+8 -5
View File
@@ -47,11 +47,6 @@
struct object_depot;
void dump_object_depot(object_depot* depot);
int dump_object_depot(int argCount, char** args);
int dump_depot_magazine(int argCount, char** args);
#if SLAB_ALLOCATION_TRACKING_AVAILABLE
class AllocationTrackingInfo {
@@ -94,6 +89,14 @@ public:
#endif // SLAB_ALLOCATION_TRACKING_AVAILABLE
void dump_object_depot(object_depot* depot);
int dump_object_depot(int argCount, char** args);
int dump_depot_magazine(int argCount, char** args);
bool slab_debug_add_allocation_for_caller(
const AllocationTrackingInfo* info, size_t allocationSize);
#if PARANOID_KERNEL_MALLOC || PARANOID_KERNEL_FREE
static inline void*
fill_block(void* buffer, size_t size, uint32 pattern)