Block size histogram added

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@5836 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: 3dab4a92eae3f6651888ea01400e84d22b85251c
Former-commit-id: ac461f1a73ff51191503504c24c4dd7212d44778
This commit is contained in:
wdbee 2014-11-14 21:58:42 +00:00
parent 8a18586843
commit e3bbf8396c
3 changed files with 152 additions and 57 deletions

View file

@ -4,7 +4,7 @@
created : Wed Nov 12 17:54:00:00 CEST 2014 created : Wed Nov 12 17:54:00:00 CEST 2014
copyright : (C) 2014 by Wolf-Dieter Beelitz copyright : (C) 2014 by Wolf-Dieter Beelitz
email : wdb at wdbee.de email : wdb at wdbee.de
version : $Id$ version : $Id:$
***************************************************************************/ ***************************************************************************/
/*************************************************************************** /***************************************************************************
@ -29,7 +29,7 @@
#include <windows.h> #include <windows.h>
#include <crtdbg.h> #include <crtdbg.h>
#include <assert.h> #include <assert.h>
#define GetRetAddrs void* retAddr = __builtin_return_address(0) #define GetRetAddrs __builtin_return_address(0)
// ... MinGW // ... MinGW
#else #else
// VC++ ... // VC++ ...
@ -40,7 +40,7 @@
#include <intrin.h> #include <intrin.h>
#pragma intrinsic(_ReturnAddress) #pragma intrinsic(_ReturnAddress)
#undef ANSI_ISO // Old VC++ versions returning NULL instead of exception #undef ANSI_ISO // Old VC++ versions returning NULL instead of exception
#define GetRetAddrs void* retAddr = _ReturnAddress() #define GetRetAddrs _ReturnAddress()
// ... VC++ // ... VC++
#endif #endif
// ... Windows // ... Windows
@ -73,9 +73,10 @@ static unsigned int GfMM_Counter = 0; // Counter of memory blocks
//============================================================================* //============================================================================*
// API: Override the global new operator // API: Override the global new operator
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
//ExternC void* operator new (size_t size)
void* operator new (size_t size) void* operator new (size_t size)
{ {
GetRetAddrs; void* retAddr = GetRetAddrs;
return GfMemoryManagerAlloc(size, GF_MM_ALLOCTYPE_NEW,retAddr); return GfMemoryManagerAlloc(size, GF_MM_ALLOCTYPE_NEW,retAddr);
} }
//============================================================================* //============================================================================*
@ -83,7 +84,8 @@ void* operator new (size_t size)
//============================================================================* //============================================================================*
// API: Override the global delete operator // API: Override the global delete operator
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
void operator delete (void *b) //ExternC void operator delete (void* b)
void operator delete (void* b)
{ {
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_NEW); GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_NEW);
} }
@ -92,9 +94,9 @@ void operator delete (void *b)
//============================================================================* //============================================================================*
// API: Override malloc // API: Override malloc
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
void * _tgf_win_malloc(size_t size) ExternC void* _tgf_win_malloc(size_t size)
{ {
GetRetAddrs; void* retAddr = GetRetAddrs;
return GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr); return GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
} }
//============================================================================* //============================================================================*
@ -102,7 +104,7 @@ void * _tgf_win_malloc(size_t size)
//============================================================================* //============================================================================*
// API: Override free // API: Override free
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
void _tgf_win_free(void * b) ExternC void _tgf_win_free(void* b)
{ {
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_MALLOC); GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_MALLOC);
} }
@ -111,10 +113,10 @@ void _tgf_win_free(void * b)
//============================================================================* //============================================================================*
// API: Override calloc // API: Override calloc
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
void * _tgf_win_calloc(size_t num, size_t size) ExternC void* _tgf_win_calloc(size_t num, size_t size)
{ {
GetRetAddrs; void* retAddr = GetRetAddrs;
void * p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr); void* p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
memset(p, 0, num * size); memset(p, 0, num * size);
return p; return p;
} }
@ -123,9 +125,9 @@ void * _tgf_win_calloc(size_t num, size_t size)
//============================================================================* //============================================================================*
// API: Override recalloc // API: Override recalloc
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
void * _tgf_win_realloc(void * memblock, size_t size) ExternC void* _tgf_win_realloc(void* memblock, size_t size)
{ {
GetRetAddrs; void* retAddr = GetRetAddrs;
if (size == 0) if (size == 0)
{ {
@ -133,7 +135,7 @@ void * _tgf_win_realloc(void * memblock, size_t size)
return NULL; return NULL;
} }
void * p = GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr); void* p = GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
if (p == NULL) if (p == NULL)
{ {
return NULL; return NULL;
@ -143,9 +145,14 @@ void * _tgf_win_realloc(void * memblock, size_t size)
{ {
if (GfMemoryManagerRunning()) if (GfMemoryManagerRunning())
{ {
size_t s = MIN(*(int*)((char*)memblock // Needed additional space
- sizeof(tDSMMLinkBlock) - sizeof(int) int bsize =
- GfMM->AddedSpace), (int)size); sizeof(tDSMMLinkBlock) // Data of Memory Manager
+ sizeof(int) // Requested size of the block
+ sizeof(int) // Marker to detect corrupted blocks
+ GfMM->AddedSpace; // Security margin for debugging
size_t s = MIN(*(int*)((char*) memblock - bsize), (int) size);
memcpy(p, memblock, s); memcpy(p, memblock, s);
} }
@ -166,9 +173,9 @@ void * _tgf_win_realloc(void * memblock, size_t size)
//============================================================================* //============================================================================*
// API: Override strdup // API: Override strdup
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
char * _tgf_win_strdup(const char * str) ExternC char * _tgf_win_strdup(const char * str)
{ {
GetRetAddrs; void* retAddr = GetRetAddrs;
char * s = (char*) GfMemoryManagerAlloc( char * s = (char*) GfMemoryManagerAlloc(
strlen(str)+1,GF_MM_ALLOCTYPE_MALLOC,retAddr); strlen(str)+1,GF_MM_ALLOCTYPE_MALLOC,retAddr);
@ -190,7 +197,7 @@ char * _tgf_win_strdup(const char * str)
//============================================================================* //============================================================================*
// Create the one and only global memory manager (allocate memory for data) // Create the one and only global memory manager (allocate memory for data)
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
tMemoryManager* GfMemoryManager() tMemoryManager* GfMemoryManager(void)
{ {
tMemoryManager* MemoryManager = (tMemoryManager*) tMemoryManager* MemoryManager = (tMemoryManager*)
malloc(sizeof(tMemoryManager)); malloc(sizeof(tMemoryManager));
@ -209,6 +216,10 @@ tMemoryManager* GfMemoryManager()
MemoryManager->GarbageCollection = (tDSMMLinkBlock*) MemoryManager; MemoryManager->GarbageCollection = (tDSMMLinkBlock*) MemoryManager;
MemoryManager->BigB = 0;
for (int I = 0; I < MAXBLOCKSIZE; I++)
MemoryManager->Hist[I] = 0;
return MemoryManager; return MemoryManager;
} }
//============================================================================* //============================================================================*
@ -260,6 +271,9 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int type, void* retAddr)
c->IDMk = MM_MARKER_ID; c->IDMk = MM_MARKER_ID;
int ID = c->BLID = GfMM_Counter++; int ID = c->BLID = GfMM_Counter++;
// Update statistics
GfMemoryManagerHist(size);
// Get address to the marker at the end // Get address to the marker at the end
char* e = (char*) c; char* e = (char*) c;
int* m = (int*) (e + bsize - sizeof(int)); int* m = (int*) (e + bsize - sizeof(int));
@ -275,7 +289,7 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int type, void* retAddr)
// Now we have here // Now we have here
// s: (int*) pointer to the size of the allocated block // s: (int*) pointer to the size of the allocated block
void* b = (void *) ++s; void* b = (void*) ++s;
// Now we have here // Now we have here
// b: (void*) official pointer to the new data block // b: (void*) official pointer to the new data block
@ -313,7 +327,7 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int type, void* retAddr)
//============================================================================* //============================================================================*
// Release memory // Release memory
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
void GfMemoryManagerFree (void *b, unsigned int type) void GfMemoryManagerFree (void* b, unsigned int type)
{ {
if (b == NULL) // If already done if (b == NULL) // If already done
return; // return without action return; // return without action
@ -323,12 +337,12 @@ void GfMemoryManagerFree (void *b, unsigned int type)
// Get start of data block ... // Get start of data block ...
int* s = (int*) b; int* s = (int*) b;
tDSMMLinkBlock* c = (tDSMMLinkBlock*) --s; tDSMMLinkBlock* c = (tDSMMLinkBlock*) --s;
c = --c; --c;
// ... Get start of data block // ... Get start of data block
// Now we have here // Now we have here
// b: (void*) official pointer to data block // b: (void*) official pointer to data block
// s: (in*) to size of allocated block // s: (int*) to size of allocated block
// c: (tDSMMLinkBlock*) to the current linked list data block // c: (tDSMMLinkBlock*) to the current linked list data block
// and will use // and will use
// n: (tDSMMLinkBlock*) to the next linked list data block // n: (tDSMMLinkBlock*) to the next linked list data block
@ -416,7 +430,7 @@ void GfMemoryManagerSetup(int AddedSpace)
//============================================================================* //============================================================================*
// Initialize the global memory manager // Initialize the global memory manager
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
bool GfMemoryManagerAllocate() bool GfMemoryManagerAllocate(void)
{ {
if (GfMM == NULL) if (GfMM == NULL)
{ {
@ -439,7 +453,7 @@ bool GfMemoryManagerAllocate()
//============================================================================* //============================================================================*
// Destroy the one and only global memory manager and it's allocated data // Destroy the one and only global memory manager and it's allocated data
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
void GfMemoryManagerRelease() void GfMemoryManagerRelease(void)
{ {
int LeakSizeTotal = 0; int LeakSizeTotal = 0;
int LeakSizeNewTotal = 0; int LeakSizeNewTotal = 0;
@ -452,6 +466,7 @@ void GfMemoryManagerRelease()
if (GfMM != NULL) if (GfMM != NULL)
{ {
tDSMMLinkBlock* Block = GfMM->GarbageCollection; tDSMMLinkBlock* Block = GfMM->GarbageCollection;
tMemoryManager* MM = GfMM;
GfMM = NULL; GfMM = NULL;
tDSMMLinkBlock* CurrentBlock = Block->Next; tDSMMLinkBlock* CurrentBlock = Block->Next;
@ -506,12 +521,33 @@ void GfMemoryManagerRelease()
fprintf(stderr,"Max leak block size new/delete : %d [Byte]\n",MaxLeakSizeNewTotal); fprintf(stderr,"Max leak block size new/delete : %d [Byte]\n",MaxLeakSizeNewTotal);
fprintf(stderr,"Max leak block size malloc/free: %d [Byte]\n",MaxLeakSizeMallocTotal); fprintf(stderr,"Max leak block size malloc/free: %d [Byte]\n",MaxLeakSizeMallocTotal);
fprintf(stderr,"Max leak block size total : %d [Byte]\n\n",MaxLeakSizeTotal); fprintf(stderr,"Max leak block size total : %d [Byte]\n",MaxLeakSizeTotal);
unsigned int total = MM->Hist[0];
for (int I = 1; I < MAXBLOCKSIZE; I++)
total += I * MM->Hist[I];
total /= (1024 * 1024); // Byte -> MB
fprintf(stderr,"\nTotal size of blocks requested : %d [MB]\n",total);
fprintf(stderr,"\nNumber of blocks >= %d [Byte] : %d",MAXBLOCKSIZE,MM->BigB);
fprintf(stderr,"\nTotal size of blocks >= %d [Byte] : %.3f [kB]",MAXBLOCKSIZE,MM->Hist[0]/1024.0);
fprintf(stderr,"\nMean size of blocks >= %d [Byte] : %.3f [kB]\n",MAXBLOCKSIZE,MM->Hist[0]/1024.0 / MM->BigB);
fprintf(stderr,"\nHistogram of block sizes < %d [Byte]:\n",MAXBLOCKSIZE);
fprintf(stderr,"\nBlocksize : Number of blocks requested\n");
for (int I = 1; I < MAXBLOCKSIZE; I++)
{
if (MM->Hist[I] > 0)
fprintf(stderr,"%04.4d : %d\n",I,MM->Hist[I]);
}
delete(Block); // Delete the memory manager itself delete(Block); // Delete the memory manager itself
} }
fprintf(stderr,"Press [Enter] to close the program\n"); fprintf(stderr,"\nPress [Enter] to close the program\n");
getchar(); getchar();
} }
//============================================================================* //============================================================================*
@ -519,7 +555,7 @@ void GfMemoryManagerRelease()
//============================================================================* //============================================================================*
// Check for Memory Manager running // Check for Memory Manager running
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
bool GfMemoryManagerRunning() bool GfMemoryManagerRunning(void)
{ {
if (GfMM != NULL) if (GfMM != NULL)
return true; return true;
@ -531,7 +567,7 @@ bool GfMemoryManagerRunning()
//============================================================================* //============================================================================*
// Set DoNotFree flag for debugging // Set DoNotFree flag for debugging
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
void GfMemoryManagerDoAccept() void GfMemoryManagerDoAccept(void)
{ {
GfMM->DoNotFree = true; GfMM->DoNotFree = true;
} }
@ -540,12 +576,27 @@ void GfMemoryManagerDoAccept()
//============================================================================* //============================================================================*
// Reset DoNotFree flag for debugging // Reset DoNotFree flag for debugging
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
void GfMemoryManagerDoFree() void GfMemoryManagerDoFree(void)
{ {
GfMM->DoNotFree = false; GfMM->DoNotFree = false;
} }
//============================================================================* //============================================================================*
//============================================================================*
// Update statistics
//----------------------------------------------------------------------------*
void GfMemoryManagerHist(size_t size)
{
if (size < MAXBLOCKSIZE)
GfMM->Hist[size] += 1;
else
{
GfMM->BigB += 1;
GfMM->Hist[0] += size;
}
}
//============================================================================*
//----------------------------------------------------------------------------* //----------------------------------------------------------------------------*
// ... Implementation // ... Implementation
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++* //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*

View file

@ -28,12 +28,12 @@
// //
// Interface // Interface
// //
TGF_API bool GfMemoryManagerAllocate(); // Initialize memory manager TGF_API bool GfMemoryManagerAllocate(void); // Initialize memory manager
TGF_API void GfMemoryManagerRelease(); // Release memory manager at Shutdown TGF_API void GfMemoryManagerRelease(void); // Release memory manager at Shutdown
TGF_API bool GfMemoryManagerRunning(); // Is the memory manager running? TGF_API bool GfMemoryManagerRunning(void); // Is the memory manager running?
TGF_API void GfMemoryManagerSetup(int AddedSpace); TGF_API void GfMemoryManagerSetup(int AddedSpace);
TGF_API void GfMemoryManagerDoAccept(); TGF_API void GfMemoryManagerDoAccept(void);
TGF_API void GfMemoryManagerDoFree(); TGF_API void GfMemoryManagerDoFree(void);
// //
// //
@ -45,25 +45,30 @@ TGF_API void GfMemoryManagerDoFree();
#define GF_MM_STATE_INIT 1 // memory manager was initialized #define GF_MM_STATE_INIT 1 // memory manager was initialized
#define GF_MM_STATE_USED 2 // memory manager was used #define GF_MM_STATE_USED 2 // memory manager was used
// Memory manager allocation types
#define GF_MM_ALLOCTYPE_MEMMAN 0 // allocation for memory manager #define GF_MM_ALLOCTYPE_MEMMAN 0 // allocation for memory manager
#define GF_MM_ALLOCTYPE_NEW 1 // allocation by new #define GF_MM_ALLOCTYPE_NEW 1 // allocation by new
#define GF_MM_ALLOCTYPE_NEWARRAY 2 // allocation by new #define GF_MM_ALLOCTYPE_NEWARRAY 2 // allocation by new
#define GF_MM_ALLOCTYPE_MALLOC 3 // allocation by calloc #define GF_MM_ALLOCTYPE_MALLOC 3 // allocation by calloc
#define MM_MARKER_BEGIN 11223344 // Memory manager check markers
#define MM_MARKER_ID 123456789 #define MM_MARKER_BEGIN 11223344 // Value of marker at start of the block
#define MM_MARKER_END 44332211 #define MM_MARKER_ID 123456789 // Value of marker in front of the ID
#define MM_MARKER_END 44332211 // Value of marker at the end of the block
// Memory manager histogram
#define MAXBLOCKSIZE 4096 // Definition of the max block size for histogram
// //
// Memory manager worker functions // Memory manager worker functions
void* GfMemoryManagerAlloc(size_t size, unsigned int type, void* RetAddr); void* GfMemoryManagerAlloc(size_t size, unsigned int type, void* retAddr);
void GfMemoryManagerFree(void* b, unsigned int type); void GfMemoryManagerFree(void* b, unsigned int type);
void GfMemoryManagerAccept(void* b, unsigned int type); void GfMemoryManagerHist(size_t size);
// //
// Block to link allocated memory blocks in a // Block to link allocated memory blocks in a
// double linked list. // double linked list and some additional flags to check
// // integrity of block at call of free
typedef struct tDSMMLinkBlock typedef struct tDSMMLinkBlock
{ {
unsigned int Mark; // Marker to identify it as tDSMMLinkBlock unsigned int Mark; // Marker to identify it as tDSMMLinkBlock
@ -89,6 +94,9 @@ typedef struct
int AddedSpace; // Number of bytes added to each block int AddedSpace; // Number of bytes added to each block
bool DoNotFree; // Do not free the blocks if flag is set bool DoNotFree; // Do not free the blocks if flag is set
unsigned int BigB; // Number of big blocks requested
unsigned int Hist[MAXBLOCKSIZE]; // Histogram of the buufer sizes
} tMemoryManager; } tMemoryManager;
// //

View file

@ -212,14 +212,41 @@ TGF_API void GfPoolMove(tMemoryPool* oldPool, tMemoryPool* newPool);
// <esppat> // <esppat>
//#define TGF_ALLOC_DEBUG 1 //#define TGF_ALLOC_DEBUG 1
//#if (defined(WIN32) && defined(TGF_ALLOC_DEBUG)) //#if (defined(WIN32) && defined(TGF_ALLOC_DEBUG))
// </esppat>
/********************************* //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
* New memory debug tools * // New Memory Manager ...
*********************************/ //----------------------------------------------------------------------------*
//============================================================================*
// Configuration for the new Memory Manager
//----------------------------------------------------------------------------*
// To enable the hunting for memory leaks uncomment the following line // To enable the hunting for memory leaks uncomment the following line
//#define __DEBUG_MEMORYMANAGER__ //#define __DEBUG_MEMORYMANAGER__
#if (defined(WIN32) && defined(__DEBUG_MEMORYMANAGER__)) #if defined(__DEBUG_MEMORYMANAGER__)
// Use new Memory Manager ...
#if defined(WIN32)
// Windows ...
#if defined(__MINGW32__)
// MinGW ...
#define ExternC extern "C"
// ... MinGW
#else
// VC++ ...
#define ExternC
// ... VC++
#endif
// ... Windows
#else
// Linux ...
// ... Linux
#endif
//============================================================================*
//============================================================================*
// Definitions of the replacements for the new Memory Manager
//----------------------------------------------------------------------------*
#define malloc _tgf_win_malloc #define malloc _tgf_win_malloc
#define calloc _tgf_win_calloc #define calloc _tgf_win_calloc
#define realloc _tgf_win_realloc #define realloc _tgf_win_realloc
@ -232,17 +259,26 @@ TGF_API void GfPoolMove(tMemoryPool* oldPool, tMemoryPool* newPool);
#endif #endif
#define strdup _tgf_win_strdup #define strdup _tgf_win_strdup
#define _strdup _tgf_win_strdup #define _strdup _tgf_win_strdup
TGF_API void * _tgf_win_malloc(size_t size); //============================================================================*
TGF_API void * _tgf_win_calloc(size_t num, size_t size);
TGF_API void * _tgf_win_realloc(void * memblock, size_t size);
TGF_API void _tgf_win_free(void * memblock);
TGF_API void _tgf_win_accept(void * memblock);
TGF_API char * _tgf_win_strdup(const char * str);
TGF_API void GfMemoryManagerDoAccept();
TGF_API void GfMemoryManagerDoFree();
#endif // WIN32 //============================================================================*
// </esppat> // Prototypes of the replacement functions for the new Memory Manager
//----------------------------------------------------------------------------*
ExternC TGF_API void* _tgf_win_malloc(size_t size);
ExternC TGF_API void* _tgf_win_calloc(size_t num, size_t size);
ExternC TGF_API void* _tgf_win_realloc(void * memblock, size_t size);
ExternC TGF_API void _tgf_win_free(void * memblock);
ExternC TGF_API void _tgf_win_accept(void * memblock);
ExternC TGF_API char* _tgf_win_strdup(const char * str);
ExternC TGF_API void GfMemoryManagerDoAccept();
ExternC TGF_API void GfMemoryManagerDoFree();
//============================================================================*
// ... Use new Memroy Manager
#endif // #if defined(__DEBUG_MEMORYMANAGER__))
//----------------------------------------------------------------------------*
// ... New Memory Manager
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
/********************************* /*********************************