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:
@@ -22,7 +22,6 @@
|
|||||||
#include "kernel_debug_config.h"
|
#include "kernel_debug_config.h"
|
||||||
|
|
||||||
#include "ObjectCache.h"
|
#include "ObjectCache.h"
|
||||||
#include "slab_debug.h"
|
|
||||||
#include "slab_private.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
|
/*static*/ status_t
|
||||||
MemoryManager::_AllocateChunks(size_t chunkSize, uint32 chunkCount,
|
MemoryManager::_AllocateChunks(size_t chunkSize, uint32 chunkCount,
|
||||||
uint32 flags, MetaChunk*& _metaChunk, Chunk*& _chunk)
|
uint32 flags, MetaChunk*& _metaChunk, Chunk*& _chunk)
|
||||||
@@ -1989,9 +2026,7 @@ void
|
|||||||
MemoryManager::_AddTrackingInfo(void* allocation, size_t size,
|
MemoryManager::_AddTrackingInfo(void* allocation, size_t size,
|
||||||
AbstractTraceEntryWithStackTrace* traceEntry)
|
AbstractTraceEntryWithStackTrace* traceEntry)
|
||||||
{
|
{
|
||||||
AllocationTrackingInfo* info = (AllocationTrackingInfo*)
|
_TrackingInfoFor(allocation, size)->Init(traceEntry);
|
||||||
((uint8*)allocation + size - sizeof(AllocationTrackingInfo));
|
|
||||||
info->Init(traceEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
|
#endif // SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
|
||||||
|
|||||||
@@ -14,8 +14,7 @@
|
|||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
#include "kernel_debug_config.h"
|
#include "slab_debug.h"
|
||||||
#include "tracing_config.h"
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractTraceEntryWithStackTrace;
|
class AbstractTraceEntryWithStackTrace;
|
||||||
@@ -61,6 +60,8 @@ public:
|
|||||||
static bool MaintenanceNeeded();
|
static bool MaintenanceNeeded();
|
||||||
static void PerformMaintenance();
|
static void PerformMaintenance();
|
||||||
|
|
||||||
|
static bool AnalyzeAllocationCallers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Tracing;
|
struct Tracing;
|
||||||
|
|
||||||
@@ -195,9 +196,11 @@ private:
|
|||||||
static int _DumpArea(int argc, char** argv);
|
static int _DumpArea(int argc, char** argv);
|
||||||
static int _DumpAreas(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,
|
static void _AddTrackingInfo(void* allocation, size_t size,
|
||||||
AbstractTraceEntryWithStackTrace* entry);
|
AbstractTraceEntryWithStackTrace* entry);
|
||||||
|
static AllocationTrackingInfo* _TrackingInfoFor(void* allocation,
|
||||||
|
size_t size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
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
|
#endif // MEMORY_MANAGER_H
|
||||||
|
|||||||
@@ -329,9 +329,6 @@ dump_cache_info(int argc, char* argv[])
|
|||||||
|
|
||||||
#if SLAB_ALLOCATION_TRACKING_AVAILABLE
|
#if SLAB_ALLOCATION_TRACKING_AVAILABLE
|
||||||
|
|
||||||
#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
|
|
||||||
// until memory manager tracking is analyzed
|
|
||||||
|
|
||||||
static caller_info*
|
static caller_info*
|
||||||
get_caller_info(addr_t caller)
|
get_caller_info(addr_t caller)
|
||||||
{
|
{
|
||||||
@@ -353,8 +350,6 @@ get_caller_info(addr_t caller)
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
caller_info_compare_size(const void* _a, const void* _b)
|
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
|
#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
analyze_allocation_callers(ObjectCache* cache, const SlabList& slabList,
|
analyze_allocation_callers(ObjectCache* cache, const SlabList& slabList)
|
||||||
size_t& _totalAllocationSize, size_t& _totalAllocationCount)
|
|
||||||
{
|
{
|
||||||
for (SlabList::ConstIterator it = slabList.GetIterator();
|
for (SlabList::ConstIterator it = slabList.GetIterator();
|
||||||
slab* slab = it.Next();) {
|
slab* slab = it.Next();) {
|
||||||
for (uint32 i = 0; i < slab->size; i++) {
|
for (uint32 i = 0; i < slab->size; i++) {
|
||||||
AllocationTrackingInfo* info = &slab->tracking[i];
|
if (!slab_debug_add_allocation_for_caller(&slab->tracking[i],
|
||||||
if (!info->IsInitialized())
|
cache->object_size)) {
|
||||||
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");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
callerInfo->count++;
|
|
||||||
callerInfo->size += cache->object_size;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,13 +418,10 @@ analyze_allocation_callers(ObjectCache* cache, const SlabList& slabList,
|
|||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
analyze_allocation_callers(ObjectCache* cache, size_t& _totalAllocationSize,
|
analyze_allocation_callers(ObjectCache* cache)
|
||||||
size_t& _totalAllocationCount)
|
|
||||||
{
|
{
|
||||||
return analyze_allocation_callers(cache, cache->full, _totalAllocationSize,
|
return analyze_allocation_callers(cache, cache->full)
|
||||||
_totalAllocationCount)
|
&& analyze_allocation_callers(cache, cache->partial);
|
||||||
&& analyze_allocation_callers(cache, cache->partial,
|
|
||||||
_totalAllocationSize, _totalAllocationCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
|
#endif // SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
|
||||||
@@ -453,12 +453,10 @@ dump_allocations_per_caller(int argc, char **argv)
|
|||||||
|
|
||||||
sCallerInfoCount = 0;
|
sCallerInfoCount = 0;
|
||||||
|
|
||||||
size_t totalAllocationSize = 0;
|
|
||||||
size_t totalAllocationCount = 0;
|
|
||||||
if (cache != NULL) {
|
if (cache != NULL) {
|
||||||
#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
|
#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING
|
||||||
analyze_allocation_callers(cache, totalAllocationSize,
|
if (!analyze_allocation_callers(cache))
|
||||||
totalAllocationCount);
|
return 0;
|
||||||
#else
|
#else
|
||||||
kprintf("Object cache allocation tracking not available. "
|
kprintf("Object cache allocation tracking not available. "
|
||||||
"SLAB_OBJECT_CACHE_TRACING (%d) and "
|
"SLAB_OBJECT_CACHE_TRACING (%d) and "
|
||||||
@@ -471,10 +469,15 @@ dump_allocations_per_caller(int argc, char **argv)
|
|||||||
ObjectCacheList::Iterator it = sObjectCaches.GetIterator();
|
ObjectCacheList::Iterator it = sObjectCaches.GetIterator();
|
||||||
|
|
||||||
while (it.HasNext()) {
|
while (it.HasNext()) {
|
||||||
analyze_allocation_callers(it.Next(), totalAllocationSize,
|
if (!analyze_allocation_callers(it.Next()))
|
||||||
totalAllocationCount);
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING
|
||||||
|
if (!MemoryManager::AnalyzeAllocationCallers())
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort the array
|
// 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,
|
kprintf("%ld different callers, sorted by %s...\n\n", sCallerInfoCount,
|
||||||
sortBySize ? "size" : "count");
|
sortBySize ? "size" : "count");
|
||||||
|
|
||||||
|
size_t totalAllocationSize = 0;
|
||||||
|
size_t totalAllocationCount = 0;
|
||||||
|
|
||||||
kprintf(" count size caller\n");
|
kprintf(" count size caller\n");
|
||||||
kprintf("----------------------------------\n");
|
kprintf("----------------------------------\n");
|
||||||
for (int32 i = 0; i < sCallerInfoCount; i++) {
|
for (int32 i = 0; i < sCallerInfoCount; i++) {
|
||||||
@@ -503,6 +509,9 @@ dump_allocations_per_caller(int argc, char **argv)
|
|||||||
exactMatch ? "" : " (nearest)");
|
exactMatch ? "" : " (nearest)");
|
||||||
} else
|
} else
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
|
|
||||||
|
totalAllocationCount += info.count;
|
||||||
|
totalAllocationSize += info.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("\ntotal allocations: %" B_PRIuSIZE ", %" B_PRIuSIZE " bytes\n",
|
kprintf("\ntotal allocations: %" B_PRIuSIZE ", %" B_PRIuSIZE " bytes\n",
|
||||||
|
|||||||
@@ -47,11 +47,6 @@
|
|||||||
struct object_depot;
|
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
|
#if SLAB_ALLOCATION_TRACKING_AVAILABLE
|
||||||
|
|
||||||
class AllocationTrackingInfo {
|
class AllocationTrackingInfo {
|
||||||
@@ -94,6 +89,14 @@ public:
|
|||||||
#endif // SLAB_ALLOCATION_TRACKING_AVAILABLE
|
#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
|
#if PARANOID_KERNEL_MALLOC || PARANOID_KERNEL_FREE
|
||||||
static inline void*
|
static inline void*
|
||||||
fill_block(void* buffer, size_t size, uint32 pattern)
|
fill_block(void* buffer, size_t size, uint32 pattern)
|
||||||
|
|||||||
Reference in New Issue
Block a user