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:
parent
8a18586843
commit
e3bbf8396c
3 changed files with 152 additions and 57 deletions
|
@ -4,7 +4,7 @@
|
|||
created : Wed Nov 12 17:54:00:00 CEST 2014
|
||||
copyright : (C) 2014 by Wolf-Dieter Beelitz
|
||||
email : wdb at wdbee.de
|
||||
version : $Id$
|
||||
version : $Id:$
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -29,7 +29,7 @@
|
|||
#include <windows.h>
|
||||
#include <crtdbg.h>
|
||||
#include <assert.h>
|
||||
#define GetRetAddrs void* retAddr = __builtin_return_address(0)
|
||||
#define GetRetAddrs __builtin_return_address(0)
|
||||
// ... MinGW
|
||||
#else
|
||||
// VC++ ...
|
||||
|
@ -40,7 +40,7 @@
|
|||
#include <intrin.h>
|
||||
#pragma intrinsic(_ReturnAddress)
|
||||
#undef ANSI_ISO // Old VC++ versions returning NULL instead of exception
|
||||
#define GetRetAddrs void* retAddr = _ReturnAddress()
|
||||
#define GetRetAddrs _ReturnAddress()
|
||||
// ... VC++
|
||||
#endif
|
||||
// ... Windows
|
||||
|
@ -73,9 +73,10 @@ static unsigned int GfMM_Counter = 0; // Counter of memory blocks
|
|||
//============================================================================*
|
||||
// API: Override the global new operator
|
||||
//----------------------------------------------------------------------------*
|
||||
//ExternC void* operator new (size_t size)
|
||||
void* operator new (size_t size)
|
||||
{
|
||||
GetRetAddrs;
|
||||
void* retAddr = GetRetAddrs;
|
||||
return GfMemoryManagerAlloc(size, GF_MM_ALLOCTYPE_NEW,retAddr);
|
||||
}
|
||||
//============================================================================*
|
||||
|
@ -83,7 +84,8 @@ void* operator new (size_t size)
|
|||
//============================================================================*
|
||||
// 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);
|
||||
}
|
||||
|
@ -92,9 +94,9 @@ void operator delete (void *b)
|
|||
//============================================================================*
|
||||
// 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);
|
||||
}
|
||||
//============================================================================*
|
||||
|
@ -102,7 +104,7 @@ void * _tgf_win_malloc(size_t size)
|
|||
//============================================================================*
|
||||
// API: Override free
|
||||
//----------------------------------------------------------------------------*
|
||||
void _tgf_win_free(void * b)
|
||||
ExternC void _tgf_win_free(void* b)
|
||||
{
|
||||
GfMemoryManagerFree(b, GF_MM_ALLOCTYPE_MALLOC);
|
||||
}
|
||||
|
@ -111,10 +113,10 @@ void _tgf_win_free(void * b)
|
|||
//============================================================================*
|
||||
// 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 * p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
|
||||
void* retAddr = GetRetAddrs;
|
||||
void* p = GfMemoryManagerAlloc(num * size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
|
||||
memset(p, 0, num * size);
|
||||
return p;
|
||||
}
|
||||
|
@ -123,9 +125,9 @@ void * _tgf_win_calloc(size_t num, size_t size)
|
|||
//============================================================================*
|
||||
// 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)
|
||||
{
|
||||
|
@ -133,7 +135,7 @@ void * _tgf_win_realloc(void * memblock, size_t size)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void * p = GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
|
||||
void* p = GfMemoryManagerAlloc(size,GF_MM_ALLOCTYPE_MALLOC,retAddr);
|
||||
if (p == NULL)
|
||||
{
|
||||
return NULL;
|
||||
|
@ -143,9 +145,14 @@ void * _tgf_win_realloc(void * memblock, size_t size)
|
|||
{
|
||||
if (GfMemoryManagerRunning())
|
||||
{
|
||||
size_t s = MIN(*(int*)((char*)memblock
|
||||
- sizeof(tDSMMLinkBlock) - sizeof(int)
|
||||
- GfMM->AddedSpace), (int)size);
|
||||
// Needed additional space
|
||||
int bsize =
|
||||
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);
|
||||
}
|
||||
|
@ -166,9 +173,9 @@ void * _tgf_win_realloc(void * memblock, size_t size)
|
|||
//============================================================================*
|
||||
// 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(
|
||||
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)
|
||||
//----------------------------------------------------------------------------*
|
||||
tMemoryManager* GfMemoryManager()
|
||||
tMemoryManager* GfMemoryManager(void)
|
||||
{
|
||||
tMemoryManager* MemoryManager = (tMemoryManager*)
|
||||
malloc(sizeof(tMemoryManager));
|
||||
|
@ -209,6 +216,10 @@ tMemoryManager* GfMemoryManager()
|
|||
|
||||
MemoryManager->GarbageCollection = (tDSMMLinkBlock*) MemoryManager;
|
||||
|
||||
MemoryManager->BigB = 0;
|
||||
for (int I = 0; I < MAXBLOCKSIZE; I++)
|
||||
MemoryManager->Hist[I] = 0;
|
||||
|
||||
return MemoryManager;
|
||||
}
|
||||
//============================================================================*
|
||||
|
@ -260,6 +271,9 @@ void* GfMemoryManagerAlloc (size_t size, unsigned int type, void* retAddr)
|
|||
c->IDMk = MM_MARKER_ID;
|
||||
int ID = c->BLID = GfMM_Counter++;
|
||||
|
||||
// Update statistics
|
||||
GfMemoryManagerHist(size);
|
||||
|
||||
// Get address to the marker at the end
|
||||
char* e = (char*) c;
|
||||
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
|
||||
// s: (int*) pointer to the size of the allocated block
|
||||
|
||||
void* b = (void *) ++s;
|
||||
void* b = (void*) ++s;
|
||||
|
||||
// Now we have here
|
||||
// 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
|
||||
//----------------------------------------------------------------------------*
|
||||
void GfMemoryManagerFree (void *b, unsigned int type)
|
||||
void GfMemoryManagerFree (void* b, unsigned int type)
|
||||
{
|
||||
if (b == NULL) // If already done
|
||||
return; // return without action
|
||||
|
@ -323,12 +337,12 @@ void GfMemoryManagerFree (void *b, unsigned int type)
|
|||
// Get start of data block ...
|
||||
int* s = (int*) b;
|
||||
tDSMMLinkBlock* c = (tDSMMLinkBlock*) --s;
|
||||
c = --c;
|
||||
--c;
|
||||
// ... Get start of data block
|
||||
|
||||
// Now we have here
|
||||
// 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
|
||||
// and will use
|
||||
// n: (tDSMMLinkBlock*) to the next linked list data block
|
||||
|
@ -416,7 +430,7 @@ void GfMemoryManagerSetup(int AddedSpace)
|
|||
//============================================================================*
|
||||
// Initialize the global memory manager
|
||||
//----------------------------------------------------------------------------*
|
||||
bool GfMemoryManagerAllocate()
|
||||
bool GfMemoryManagerAllocate(void)
|
||||
{
|
||||
if (GfMM == NULL)
|
||||
{
|
||||
|
@ -439,7 +453,7 @@ bool GfMemoryManagerAllocate()
|
|||
//============================================================================*
|
||||
// Destroy the one and only global memory manager and it's allocated data
|
||||
//----------------------------------------------------------------------------*
|
||||
void GfMemoryManagerRelease()
|
||||
void GfMemoryManagerRelease(void)
|
||||
{
|
||||
int LeakSizeTotal = 0;
|
||||
int LeakSizeNewTotal = 0;
|
||||
|
@ -452,6 +466,7 @@ void GfMemoryManagerRelease()
|
|||
if (GfMM != NULL)
|
||||
{
|
||||
tDSMMLinkBlock* Block = GfMM->GarbageCollection;
|
||||
tMemoryManager* MM = GfMM;
|
||||
GfMM = NULL;
|
||||
|
||||
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 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
|
||||
}
|
||||
|
||||
fprintf(stderr,"Press [Enter] to close the program\n");
|
||||
fprintf(stderr,"\nPress [Enter] to close the program\n");
|
||||
getchar();
|
||||
}
|
||||
//============================================================================*
|
||||
|
@ -519,7 +555,7 @@ void GfMemoryManagerRelease()
|
|||
//============================================================================*
|
||||
// Check for Memory Manager running
|
||||
//----------------------------------------------------------------------------*
|
||||
bool GfMemoryManagerRunning()
|
||||
bool GfMemoryManagerRunning(void)
|
||||
{
|
||||
if (GfMM != NULL)
|
||||
return true;
|
||||
|
@ -531,7 +567,7 @@ bool GfMemoryManagerRunning()
|
|||
//============================================================================*
|
||||
// Set DoNotFree flag for debugging
|
||||
//----------------------------------------------------------------------------*
|
||||
void GfMemoryManagerDoAccept()
|
||||
void GfMemoryManagerDoAccept(void)
|
||||
{
|
||||
GfMM->DoNotFree = true;
|
||||
}
|
||||
|
@ -540,11 +576,26 @@ void GfMemoryManagerDoAccept()
|
|||
//============================================================================*
|
||||
// Reset DoNotFree flag for debugging
|
||||
//----------------------------------------------------------------------------*
|
||||
void GfMemoryManagerDoFree()
|
||||
void GfMemoryManagerDoFree(void)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
//
|
||||
// Interface
|
||||
//
|
||||
TGF_API bool GfMemoryManagerAllocate(); // Initialize memory manager
|
||||
TGF_API void GfMemoryManagerRelease(); // Release memory manager at Shutdown
|
||||
TGF_API bool GfMemoryManagerRunning(); // Is the memory manager running?
|
||||
TGF_API bool GfMemoryManagerAllocate(void); // Initialize memory manager
|
||||
TGF_API void GfMemoryManagerRelease(void); // Release memory manager at Shutdown
|
||||
TGF_API bool GfMemoryManagerRunning(void); // Is the memory manager running?
|
||||
TGF_API void GfMemoryManagerSetup(int AddedSpace);
|
||||
TGF_API void GfMemoryManagerDoAccept();
|
||||
TGF_API void GfMemoryManagerDoFree();
|
||||
TGF_API void GfMemoryManagerDoAccept(void);
|
||||
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_USED 2 // memory manager was used
|
||||
|
||||
// Memory manager allocation types
|
||||
#define GF_MM_ALLOCTYPE_MEMMAN 0 // allocation for memory manager
|
||||
#define GF_MM_ALLOCTYPE_NEW 1 // allocation by new
|
||||
#define GF_MM_ALLOCTYPE_NEWARRAY 2 // allocation by new
|
||||
#define GF_MM_ALLOCTYPE_MALLOC 3 // allocation by calloc
|
||||
|
||||
#define MM_MARKER_BEGIN 11223344
|
||||
#define MM_MARKER_ID 123456789
|
||||
#define MM_MARKER_END 44332211
|
||||
// Memory manager check markers
|
||||
#define MM_MARKER_BEGIN 11223344 // Value of marker at start of the block
|
||||
#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
|
||||
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 GfMemoryManagerAccept(void* b, unsigned int type);
|
||||
void GfMemoryManagerHist(size_t size);
|
||||
//
|
||||
|
||||
// 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
|
||||
{
|
||||
unsigned int Mark; // Marker to identify it as tDSMMLinkBlock
|
||||
|
@ -89,6 +94,9 @@ typedef struct
|
|||
int AddedSpace; // Number of bytes added to each block
|
||||
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;
|
||||
//
|
||||
|
||||
|
|
|
@ -212,14 +212,41 @@ TGF_API void GfPoolMove(tMemoryPool* oldPool, tMemoryPool* newPool);
|
|||
// <esppat>
|
||||
//#define TGF_ALLOC_DEBUG 1
|
||||
//#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
|
||||
//#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 calloc _tgf_win_calloc
|
||||
#define realloc _tgf_win_realloc
|
||||
|
@ -232,17 +259,26 @@ TGF_API void GfPoolMove(tMemoryPool* oldPool, tMemoryPool* newPool);
|
|||
#endif
|
||||
#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
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
|
||||
|
||||
|
||||
/*********************************
|
||||
|
|
Loading…
Reference in a new issue