382 lines
9.3 KiB
C++
382 lines
9.3 KiB
C++
/*++
|
||
|
||
Copyright (c) 1995-1997 Microsoft Corporation
|
||
|
||
Module Name :
|
||
heapstat.cxx
|
||
|
||
Abstract:
|
||
This module contains functions for handling heap related probes.
|
||
|
||
Author:
|
||
|
||
Murali R. Krishnan ( MuraliK ) 3-Nov-1997
|
||
|
||
Environment:
|
||
|
||
Win32 - User Mode
|
||
|
||
Project:
|
||
|
||
Internet Server Probe DLL
|
||
|
||
Functions Exported:
|
||
|
||
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
/************************************************************
|
||
* Include Headers
|
||
************************************************************/
|
||
//
|
||
// Turn off dllexp so this DLL won't export tons of unnecessary garbage.
|
||
//
|
||
|
||
#ifdef dllexp
|
||
#undef dllexp
|
||
#endif
|
||
#define dllexp
|
||
|
||
# include "iisprobe.hxx"
|
||
|
||
|
||
/************************************************************
|
||
* Functions
|
||
************************************************************/
|
||
|
||
VOID
|
||
HEAP_BLOCK_STATS::AddStatistics( const HEAP_BLOCK_STATS & heapEnumAddend)
|
||
{
|
||
|
||
//
|
||
// Walk through the blocks list and accumulate sum
|
||
//
|
||
|
||
DWORD i; // index for block size
|
||
for( i = 0 ; i < MAX_HEAP_BLOCK_SIZE ; i++ ) {
|
||
|
||
if( heapEnumAddend.BusyCounters[i] != 0 ) {
|
||
this->BusyCounters[i] += heapEnumAddend.BusyCounters[i];
|
||
}
|
||
|
||
if ( heapEnumAddend.FreeCounters[i] != 0 ) {
|
||
this->FreeCounters[i] += heapEnumAddend.FreeCounters[i];
|
||
}
|
||
} // for
|
||
|
||
|
||
if ( heapEnumAddend.BusyJumbo != 0) {
|
||
this->BusyJumbo += heapEnumAddend.BusyJumbo;
|
||
this->BusyJumboBytes += heapEnumAddend.BusyJumboBytes;
|
||
}
|
||
|
||
if ( heapEnumAddend.FreeJumbo != 0) {
|
||
|
||
this->FreeJumbo += heapEnumAddend.FreeJumbo;
|
||
this->FreeJumboBytes += heapEnumAddend.FreeJumboBytes;
|
||
}
|
||
|
||
return;
|
||
} // HEAP_BLOCK_STATS::AddStatistics()
|
||
|
||
|
||
|
||
VOID
|
||
HEAP_BLOCK_STATS::UpdateBlockStats(
|
||
IN LPPROCESS_HEAP_ENTRY lpLocalHeapEntry
|
||
)
|
||
/*++
|
||
Description:
|
||
This function looks at the data present in the lpLocalHeapEntry and updates
|
||
internal statistics for blocks using that information.
|
||
Note: We ignore the cbOverhead field
|
||
|
||
Arguments:
|
||
lpLocalHeapEntry - pointer to Win32 object with details on Process heap entry
|
||
|
||
Retruns:
|
||
None
|
||
--*/
|
||
{
|
||
DWORD entryLength;
|
||
|
||
# if DETAILED_BLOCK_INFO
|
||
CHAR rgchHeapEntry[200];
|
||
wsprintf( rgchHeapEntry, "%08x: @%08x, cbData=%d, cbOver=%d, iRegion=%d, Flags=%08x\n",
|
||
lpLocalHeapEntry,
|
||
lpLocalHeapEntry->lpData,
|
||
lpLocalHeapEntry->cbData,
|
||
lpLocalHeapEntry->cbOverhead,
|
||
lpLocalHeapEntry->iRegionIndex,
|
||
lpLocalHeapEntry->wFlags
|
||
);
|
||
OutputDebugString( rgchHeapEntry);
|
||
# endif // DETAILED_BLOCK_INFO
|
||
|
||
entryLength = lpLocalHeapEntry->cbData;
|
||
|
||
if( lpLocalHeapEntry->wFlags & PROCESS_HEAP_ENTRY_BUSY ) {
|
||
|
||
if( entryLength < MAX_HEAP_BLOCK_SIZE ) {
|
||
BusyCounters[entryLength] += 1;
|
||
} else {
|
||
BusyJumbo ++;
|
||
BusyJumboBytes += entryLength;
|
||
}
|
||
|
||
} else {
|
||
|
||
if( entryLength < MAX_HEAP_BLOCK_SIZE ) {
|
||
FreeCounters[entryLength] += 1;
|
||
} else {
|
||
FreeJumbo ++;
|
||
FreeJumboBytes += entryLength;
|
||
}
|
||
|
||
}
|
||
|
||
return;
|
||
} // HEAP_BLOCK_STATS::UpdateBlockStats()
|
||
|
||
|
||
VOID
|
||
HEAP_BLOCK_STATS::UpdateBlockStats(IN LPHEAPENTRY32 lpHeapEntry)
|
||
/*++
|
||
Description:
|
||
This function looks at the data present in the Win95 HeapEntry and updates
|
||
internal statistics for blocks using that information.
|
||
Note: We ignore the cbOverhead field
|
||
|
||
Arguments:
|
||
lpHeapEntry - pointer to Win95 object with details on Process heap entry
|
||
|
||
Retruns:
|
||
None
|
||
--*/
|
||
{
|
||
|
||
DWORD entryLength;
|
||
|
||
# if DETAILED_BLOCK_INFO
|
||
|
||
CHAR rgchHeapEntry[200];
|
||
|
||
wsprintf( rgchHeapEntry, "%08x: @%08x, cbData=%d, Flags=%08x\n",
|
||
lpHeapEntry,
|
||
lpHeapEntry->dwAddress,
|
||
lpHeapEntry->dwBlockSize,
|
||
lpHeapEntry->dwFlags
|
||
);
|
||
|
||
OutputDebugString( rgchHeapEntry);
|
||
|
||
# endif // DETAILED_BLOCK_INFO
|
||
|
||
entryLength = (DWORD)lpHeapEntry->dwBlockSize;
|
||
|
||
if( lpHeapEntry->dwFlags & LF32_FREE ) {
|
||
|
||
if( entryLength < MAX_HEAP_BLOCK_SIZE ) {
|
||
FreeCounters[entryLength] += 1;
|
||
} else {
|
||
FreeJumbo ++;
|
||
FreeJumboBytes += entryLength;
|
||
}
|
||
|
||
} else {
|
||
|
||
if( entryLength < MAX_HEAP_BLOCK_SIZE ) {
|
||
BusyCounters[entryLength] += 1;
|
||
} else {
|
||
BusyJumbo ++;
|
||
BusyJumboBytes += entryLength;
|
||
}
|
||
}
|
||
|
||
return;
|
||
} // HEAP_BLOCK_STATS::UpdateBlockStats()
|
||
|
||
|
||
BOOL
|
||
HEAP_BLOCK_STATS::LoadHeapStats( IN PHANDLE phHeap)
|
||
/*++
|
||
Description:
|
||
This function loads the heap block statistics for given heap handle
|
||
into the current object.
|
||
|
||
Arguments:
|
||
phHeap - pointer to Handle for the heap we are interested in.
|
||
|
||
Returns:
|
||
TRUE on success and FALSE on failure
|
||
|
||
Note: "this" object should have been initialized before this call
|
||
Initialization can be done by calling Reset() method
|
||
--*/
|
||
{
|
||
BOOL fReturn = TRUE;
|
||
|
||
DBG_ASSERT( phHeap != NULL);
|
||
|
||
//
|
||
// 1. Lock the heap so that there is no interference from other threads
|
||
//
|
||
|
||
if ( HeapLock( phHeap)) {
|
||
|
||
PROCESS_HEAP_ENTRY heapEntry; // Win32 heap entry structure
|
||
ZeroMemory( (PVOID ) &heapEntry, sizeof(heapEntry)); // initailize heap entry struct
|
||
|
||
//
|
||
// 2. Walk the heap enumerating all the blocks
|
||
//
|
||
|
||
while ( HeapWalk( phHeap, &heapEntry)) {
|
||
|
||
UpdateBlockStats( &heapEntry);
|
||
} // while
|
||
|
||
|
||
//
|
||
// 3. Unlock the heap before return
|
||
//
|
||
|
||
DBG_REQUIRE( HeapUnlock( phHeap));
|
||
} else {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "Unable to lock heap(%08x)\n", phHeap));
|
||
fReturn = FALSE;
|
||
}
|
||
|
||
return ( fReturn);
|
||
} // HEAP_BLOCK_STATS::LoadHeapStats()
|
||
|
||
|
||
BOOL
|
||
HEAP_BLOCK_STATS::LoadHeapStats(
|
||
IN LPHEAPLIST32 phl32,
|
||
IN HEAPBLOCKWALK pHeap32First,
|
||
IN HEAPBLOCKWALK pHeap32Next
|
||
)
|
||
/*++
|
||
Description:
|
||
This function loads the Win95 heap block statistics for given heap
|
||
into the current object.
|
||
|
||
Arguments:
|
||
phl32 - pointer to heap list entry for the heap we r interested in.
|
||
pHeap32First - pointer to function for enumerating First heap block
|
||
pHeap32Next - pointer to function for enumerating Next heap block
|
||
|
||
Returns:
|
||
TRUE on success and FALSE on failure
|
||
|
||
Note: "this" object should have been initialized before this call
|
||
Initialization can be done by calling Reset() method
|
||
--*/
|
||
{
|
||
BOOL fReturn = TRUE;
|
||
|
||
DBG_ASSERT( phl32 != NULL);
|
||
|
||
HEAPENTRY32 heapEntry;
|
||
|
||
ZeroMemory( (PVOID ) &heapEntry, sizeof(heapEntry)); // initailize heap entry struct
|
||
heapEntry.dwSize = sizeof(HEAPENTRY32);
|
||
|
||
//
|
||
// Walk the heap enumerating all the blocks
|
||
//
|
||
|
||
if ( pHeap32First(&heapEntry, phl32->th32ProcessID, phl32->th32HeapID) )
|
||
{
|
||
UpdateBlockStats(&heapEntry);
|
||
|
||
while ( pHeap32Next( &heapEntry, phl32->th32ProcessID, phl32->th32HeapID)) {
|
||
|
||
UpdateBlockStats( &heapEntry);
|
||
} // while
|
||
}
|
||
|
||
return ( fReturn);
|
||
|
||
} // HEAP_BLOCK_STATS::LoadHeapStats()
|
||
|
||
|
||
|
||
/**********************************************************************
|
||
* Member Functions of HEAP_STATS
|
||
**********************************************************************/
|
||
|
||
VOID
|
||
HEAP_STATS::ExtractStatsFromBlockStats( const HEAP_BLOCK_STATS * pheapBlockStats)
|
||
{
|
||
|
||
//
|
||
// initialize statistics to be nothing
|
||
//
|
||
ZeroMemory( this, sizeof( *this));
|
||
|
||
//
|
||
// Walk through the cumulative statistics structure and extract sum
|
||
//
|
||
|
||
DWORD i; // index for block size
|
||
for( i = 0 ; i < MAX_HEAP_BLOCK_SIZE ; i++ ) {
|
||
|
||
if( pheapBlockStats->BusyCounters[i] != 0) {
|
||
|
||
this->m_BusyBlocks += pheapBlockStats->BusyCounters[i];
|
||
this->m_BusyBytes += i * pheapBlockStats->BusyCounters[i];
|
||
}
|
||
|
||
if ( pheapBlockStats->FreeCounters[i] != 0 ) {
|
||
|
||
this->m_FreeBlocks += pheapBlockStats->FreeCounters[i];
|
||
this->m_FreeBytes += i * pheapBlockStats->FreeCounters[i];
|
||
}
|
||
} // for
|
||
|
||
|
||
if( pheapBlockStats->BusyJumbo != 0) {
|
||
|
||
this->m_BusyBlocks += pheapBlockStats->BusyJumbo;
|
||
this->m_BusyBytes += pheapBlockStats->BusyJumboBytes;
|
||
}
|
||
|
||
if ( pheapBlockStats->FreeJumbo != 0 ) {
|
||
|
||
this->m_FreeBlocks += pheapBlockStats->FreeJumbo;
|
||
this->m_FreeBytes += pheapBlockStats->FreeJumboBytes;
|
||
}
|
||
|
||
return;
|
||
|
||
} // HEAP_STATS::ExtractStatsFromBlockStats()
|
||
|
||
|
||
|
||
VOID
|
||
HEAP_STATS::AddStatistics( const HEAP_STATS & heapStats)
|
||
{
|
||
|
||
//
|
||
// Accumulate the statistics from heapStats into the current object
|
||
//
|
||
|
||
m_BusyBlocks += heapStats.m_BusyBlocks;
|
||
m_BusyBytes += heapStats.m_BusyBytes;
|
||
|
||
m_FreeBlocks += heapStats.m_FreeBlocks;
|
||
m_FreeBytes += heapStats.m_FreeBytes;
|
||
|
||
return;
|
||
} // HEAP_STATS::AddStatistics()
|
||
|
||
|
||
/************************ End of File ***********************/
|