|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// SHOW_MEMDUMP.CPP
//
// Show Mem Dump Display.
//=====================================================================================//
#include "vxconsole.h"
#define ID_SHOWMEMDUMP_LISTVIEW 100
// column id, pool mode
#define ID_DUMPPOOL_POOL 0
#define ID_DUMPPOOL_SIZE 1
#define ID_DUMPPOOL_ALLOCATED 2
#define ID_DUMPPOOL_FREE 3
#define ID_DUMPPOOL_COMMITTED 4
#define ID_DUMPPOOL_COMMITTEDSIZE 5
// column id, detailed mode
#define ID_DUMPDETAIL_ALLOCATION 0
#define ID_DUMPDETAIL_CURRENTSIZE 1
#define ID_DUMPDETAIL_PEAKSIZE 2
#define ID_DUMPDETAIL_TOTALSIZE 3
#define ID_DUMPDETAIL_OVERHEAD 4
#define ID_DUMPDETAIL_PEAKOVERHEAD 5
#define ID_DUMPDETAIL_TIME 6
#define ID_DUMPDETAIL_CURRENTCOUNT 7
#define ID_DUMPDETAIL_PEAKCOUNT 8
#define ID_DUMPDETAIL_TOTALCOUNT 9
#define ID_DUMPDETAIL_LTE16 10
#define ID_DUMPDETAIL_LTE32 11
#define ID_DUMPDETAIL_LTE128 12
#define ID_DUMPDETAIL_LTE1024 13
#define ID_DUMPDETAIL_GT1024 14
#define SHOW_BYTES 0
#define SHOW_KILOBYTES 1
#define SHOW_MEGABYTES 2
#define FORMAT_POOLS 0
#define FORMAT_DETAILS 1
struct MemoryPool_t { int pool; char poolBuff[32]; int size; char sizeBuff[32]; int allocated; char allocatedBuff[32]; int free; char freeBuff[32]; int committed; char committedBuff[32]; int committedSize; char committedSizeBuff[32]; };
struct MemoryDetail_t { char *pAllocationName; int currentSize; char currentSizeBuff[32]; int peakSize; char peakSizeBuff[32]; int totalSize; char totalSizeBuff[32]; int overheadSize; char overheadSizeBuff[32]; int peakOverheadSize; char peakOverheadSizeBuff[32]; int time; char timeBuff[32]; int currentCount; char currentCountBuff[32]; int peakCount; char peakCountBuff[32]; int totalCount; char totalCountBuff[32]; int lte16; char lte16Buff[32]; int lte32; char lte32Buff[32]; int lte128; char lte128Buff[32]; int lte1024; char lte1024Buff[32]; int gt1024; char gt1024Buff[32]; };
struct memory_t { int listIndex; MemoryPool_t pool; MemoryDetail_t detail; };
struct label_t { const CHAR* name; int width; int subItemIndex; CHAR nameBuff[64]; };
HWND g_showMemDump_hWnd; HWND g_showMemDump_hWndListView; RECT g_showMemDump_windowRect; int g_showMemDump_sortColumn; int g_showMemDump_sortDescending; memory_t *g_showMemDump_pMemory; int g_showMemDump_numMemory; int g_showMemDump_showBytes; bool g_showMemDump_bCollapseOutput; char g_showMemDump_currentFilename[MAX_PATH]; int g_showMemDump_format;
void ShowMemDump_Parse( const char *pBuffer, int fileSize );
label_t g_showMemDump_PoolLabels[] = { {"Pool", 120, ID_DUMPPOOL_POOL}, {"Size", 120, ID_DUMPPOOL_SIZE}, {"Allocated Count", 120, ID_DUMPPOOL_ALLOCATED}, {"Free Count", 120, ID_DUMPPOOL_FREE}, {"Committed Count", 120, ID_DUMPPOOL_COMMITTED}, {"Committed Size", 120, ID_DUMPPOOL_COMMITTEDSIZE}, };
label_t g_showMemDump_DetailLabels[] = { {"Allocation", 200, ID_DUMPDETAIL_ALLOCATION}, {"Current Size", 120, ID_DUMPDETAIL_CURRENTSIZE}, {"Peak Size", 120, ID_DUMPDETAIL_PEAKSIZE}, {"Total Allocations", 120, ID_DUMPDETAIL_TOTALSIZE}, {"Overhead Size", 120, ID_DUMPDETAIL_OVERHEAD}, {"Peak Overhead Size", 120, ID_DUMPDETAIL_PEAKOVERHEAD}, {"Time (ms)", 120, ID_DUMPDETAIL_TIME}, {"Current Count", 120, ID_DUMPDETAIL_CURRENTCOUNT}, {"Peak Count", 120, ID_DUMPDETAIL_PEAKCOUNT}, {"Total Count", 120, ID_DUMPDETAIL_TOTALCOUNT}, {"<=16 bytes", 100, ID_DUMPDETAIL_LTE16}, {"17-32 bytes", 100, ID_DUMPDETAIL_LTE32}, {"33-128 bytes", 100, ID_DUMPDETAIL_LTE128}, {"129-1024 bytes", 100, ID_DUMPDETAIL_LTE1024}, {"> 1024 bytes", 100, ID_DUMPDETAIL_GT1024}, };
//-----------------------------------------------------------------------------
// ShowMemDump_FormatSize
//
//-----------------------------------------------------------------------------
char *ShowMemDump_FormatSize( int size, char *pBuff, bool bUnits ) { switch ( g_showMemDump_showBytes ) { case SHOW_BYTES: sprintf( pBuff, "%d", size ); break;
case SHOW_KILOBYTES: sprintf( pBuff, "%.2f", (float)size/1024.0f ); if ( bUnits ) strcat( pBuff, " K"); break;
case SHOW_MEGABYTES: sprintf( pBuff, "%.2f", (float)size/(1024.0f*1024.0f) ); if ( bUnits ) strcat( pBuff, " MB"); break; }
return pBuff; }
//-----------------------------------------------------------------------------
// ShowMemDump_SaveConfig
//
//-----------------------------------------------------------------------------
void ShowMemDump_SaveConfig() { char buff[256];
Sys_SetRegistryInteger( "showMemDumpSortColumn", g_showMemDump_sortColumn ); Sys_SetRegistryInteger( "showMemDumpSortDescending", g_showMemDump_sortDescending ); Sys_SetRegistryInteger( "showMemDumpShowBytes", g_showMemDump_showBytes );
WINDOWPLACEMENT wp; memset( &wp, 0, sizeof( wp ) ); wp.length = sizeof( WINDOWPLACEMENT ); GetWindowPlacement( g_showMemDump_hWnd, &wp ); g_showMemDump_windowRect = wp.rcNormalPosition;
sprintf( buff, "%d %d %d %d", g_showMemDump_windowRect.left, g_showMemDump_windowRect.top, g_showMemDump_windowRect.right, g_showMemDump_windowRect.bottom ); Sys_SetRegistryString( "showMemDumpWindowRect", buff ); }
//-----------------------------------------------------------------------------
// ShowMemDump_LoadConfig
//
//-----------------------------------------------------------------------------
void ShowMemDump_LoadConfig() { int numArgs; char buff[256];
Sys_GetRegistryInteger( "showMemDumpSortColumn", 0, g_showMemDump_sortColumn ); Sys_GetRegistryInteger( "showMemDumpSortDescending", false, g_showMemDump_sortDescending ); Sys_GetRegistryInteger( "showMemDumpShowBytes", SHOW_KILOBYTES, g_showMemDump_showBytes );
Sys_GetRegistryString( "showMemDumpWindowRect", buff, "", sizeof( buff ) ); numArgs = sscanf( buff, "%d %d %d %d", &g_showMemDump_windowRect.left, &g_showMemDump_windowRect.top, &g_showMemDump_windowRect.right, &g_showMemDump_windowRect.bottom ); if ( numArgs != 4 || g_showMemDump_windowRect.left < 0 || g_showMemDump_windowRect.top < 0 || g_showMemDump_windowRect.right < 0 || g_showMemDump_windowRect.bottom < 0 ) memset( &g_showMemDump_windowRect, 0, sizeof( g_showMemDump_windowRect ) ); }
//-----------------------------------------------------------------------------
// ShowMemDump_Clear
//
//-----------------------------------------------------------------------------
void ShowMemDump_Clear() { // delete all the list view entries
if ( g_showMemDump_hWnd ) { ListView_DeleteAllItems( g_showMemDump_hWndListView ); }
if ( !g_showMemDump_pMemory ) return;
for ( int i=0; i<g_showMemDump_numMemory; i++ ) { delete [] g_showMemDump_pMemory[i].detail.pAllocationName; }
Sys_Free( g_showMemDump_pMemory );
g_showMemDump_pMemory = NULL; g_showMemDump_numMemory = 0; }
//-----------------------------------------------------------------------------
// ShowMemDump_Export
//
//-----------------------------------------------------------------------------
void ShowMemDump_Export() { OPENFILENAME ofn; char logFilename[MAX_PATH]; int retval; FILE* fp; int i; char buff[64];
if ( g_showMemDump_format != FORMAT_DETAILS ) { return; }
memset( &ofn, 0, sizeof( ofn ) ); ofn.lStructSize = sizeof( ofn ); ofn.hwndOwner = g_showMemDump_hWnd; ofn.lpstrFile = logFilename; ofn.lpstrFile[0] = '\0'; ofn.nMaxFile = sizeof( logFilename ); ofn.lpstrFilter = "Excel CSV\0*.CSV\0All Files\0*.*\0"; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = "c:\\"; ofn.Flags = OFN_PATHMUSTEXIST;
// display the Open dialog box.
retval = GetOpenFileName( &ofn ); if ( !retval ) return;
Sys_AddExtension( ".csv", logFilename, sizeof( logFilename ) );
fp = fopen( logFilename, "wt+" ); if ( !fp ) return;
// labels
fprintf( fp, "Allocation Type" ); fprintf( fp, ",Current Size" ); fprintf( fp, ",Peak Size" ); fprintf( fp, ",Total Allocations" ); fprintf( fp, ",Overhead Size" ); fprintf( fp, ",Peak Overhead Size" ); fprintf( fp, ",Time(ms)" ); fprintf( fp, ",Current Count" ); fprintf( fp, ",Peak Count" ); fprintf( fp, ",Total Count" ); fprintf( fp, ",<=16 Byte Allocations" ); fprintf( fp, ",17-32 Byte Allocations" ); fprintf( fp, ",33-128 Byte Allocations" ); fprintf( fp, ",129-1024 Byte Allocations" ); fprintf( fp, ",>1024 Byte Allocations" ); fprintf( fp, "\n" );
// dump to the log
for ( i=0; i<g_showMemDump_numMemory; i++ ) { fprintf( fp, "\"%s\"", g_showMemDump_pMemory[i].detail.pAllocationName ); fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.currentSize, buff, false ) ); fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakSize, buff, false ) ); fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.totalSize, buff, false ) ); fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.overheadSize, buff, false ) ); fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakOverheadSize, buff, false ) ); fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.time ); fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.currentCount ); fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.peakCount ); fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.totalCount ); fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte16 ); fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte32 ); fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte128 ); fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte1024 ); fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.gt1024 ); fprintf( fp, "\n" ); }
fclose( fp ); }
//-----------------------------------------------------------------------------
// ShowMemDump_Summary
//
//-----------------------------------------------------------------------------
void ShowMemDump_Summary() { char buff[1024]; int i;
if ( g_showMemDump_format != FORMAT_DETAILS ) { return; }
int currentSize = 0; int peakSize = 0; int totalSize = 0; int overheadSize = 0; int peakOverheadSize = 0; int time = 0; int currentCount = 0; int peakCount = 0; int totalCount = 0; int lte16 = 0; int lte32 = 0; int lte128 = 0; int lte1024 = 0; int gt1024 = 0;
// tally the totals
for (i=0; i<g_showMemDump_numMemory; i++) { if ( !strnicmp( g_showMemDump_pMemory[i].detail.pAllocationName, "Totals,", 7 ) ) continue;
currentSize += g_showMemDump_pMemory[i].detail.currentSize; peakSize += g_showMemDump_pMemory[i].detail.peakSize; totalSize += g_showMemDump_pMemory[i].detail.totalSize; overheadSize += g_showMemDump_pMemory[i].detail.overheadSize; peakOverheadSize += g_showMemDump_pMemory[i].detail.peakOverheadSize; time += g_showMemDump_pMemory[i].detail.time; currentCount += g_showMemDump_pMemory[i].detail.currentCount; peakCount += g_showMemDump_pMemory[i].detail.peakCount; totalCount += g_showMemDump_pMemory[i].detail.totalCount; lte16 += g_showMemDump_pMemory[i].detail.lte16; lte32 += g_showMemDump_pMemory[i].detail.lte32; lte128 += g_showMemDump_pMemory[i].detail.lte128; lte1024 += g_showMemDump_pMemory[i].detail.lte1024; gt1024 += g_showMemDump_pMemory[i].detail.gt1024; }
sprintf( buff, "Entries:\t\t\t%d\n" "Current Size:\t\t%.2f MB\n" "Peak Size:\t\t%.2f MB\n" "Total Size:\t\t%.2f MB\n" "Overhead Size:\t\t%d\n" "Peak Overhead Size:\t%d\n" "Time:\t\t\t%d\n" "Current Count:\t\t%d\n" "Peak Count:\t\t%d\n" "Total Count:\t\t%d\n" "<= 16:\t\t\t%d\n" "17-32:\t\t\t%d\n" "33-128:\t\t\t%d\n" "129-1024:\t\t%d\n" "> 1024:\t\t\t%d\n", g_showMemDump_numMemory, (float)currentSize/( 1024.0F*1024.0F ), (float)peakSize/( 1024.0F*1024.0F ), (float)totalSize/( 1024.0F*1024.0F ), overheadSize, peakOverheadSize, time, currentCount, peakCount, totalCount, lte16, lte32, lte128, lte1024, gt1024 );
MessageBox( g_showMemDump_hWnd, buff, "Memory Dump Summary", MB_OK|MB_APPLMODAL ); }
//-----------------------------------------------------------------------------
// ShowMemDump_SetTitle
//
//-----------------------------------------------------------------------------
void ShowMemDump_SetTitle() { if ( g_showMemDump_hWnd ) { SetWindowText( g_showMemDump_hWnd, "Memory Dump" ); } }
//-----------------------------------------------------------------------------
// ShowMemDump_CompareFunc
//
//-----------------------------------------------------------------------------
int CALLBACK ShowMemDump_CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ) { memory_t* pMemoryA = (memory_t*)lParam1; memory_t* pMemoryB = (memory_t*)lParam2;
int sort = 0;
if ( g_showMemDump_format == FORMAT_POOLS ) { switch ( g_showMemDump_sortColumn ) { case ID_DUMPPOOL_POOL: sort = pMemoryA->pool.pool - pMemoryB->pool.pool; break;
case ID_DUMPPOOL_SIZE: sort = pMemoryA->pool.size - pMemoryB->pool.size; break;
case ID_DUMPPOOL_ALLOCATED: sort = pMemoryA->pool.allocated - pMemoryB->pool.allocated; break;
case ID_DUMPPOOL_FREE: sort = pMemoryA->pool.free - pMemoryB->pool.free; break;
case ID_DUMPPOOL_COMMITTED: sort = pMemoryA->pool.committed - pMemoryB->pool.committed; break;
case ID_DUMPPOOL_COMMITTEDSIZE: sort = pMemoryA->pool.committedSize - pMemoryB->pool.committedSize; break; } } else { switch ( g_showMemDump_sortColumn ) { case ID_DUMPDETAIL_ALLOCATION: sort = stricmp( pMemoryA->detail.pAllocationName, pMemoryB->detail.pAllocationName ); break;
case ID_DUMPDETAIL_CURRENTSIZE: sort = pMemoryA->detail.currentSize - pMemoryB->detail.currentSize; break;
case ID_DUMPDETAIL_PEAKSIZE: sort = pMemoryA->detail.peakSize - pMemoryB->detail.peakSize; break;
case ID_DUMPDETAIL_TOTALSIZE: sort = pMemoryA->detail.totalSize - pMemoryB->detail.totalSize; break;
case ID_DUMPDETAIL_OVERHEAD: sort = pMemoryA->detail.overheadSize - pMemoryB->detail.overheadSize; break;
case ID_DUMPDETAIL_PEAKOVERHEAD: sort = pMemoryA->detail.peakOverheadSize - pMemoryB->detail.peakOverheadSize; break;
case ID_DUMPDETAIL_TIME: sort = pMemoryA->detail.time - pMemoryB->detail.time; break;
case ID_DUMPDETAIL_CURRENTCOUNT: sort = pMemoryA->detail.currentCount - pMemoryB->detail.currentCount; break;
case ID_DUMPDETAIL_PEAKCOUNT: sort = pMemoryA->detail.peakCount - pMemoryB->detail.peakCount; break;
case ID_DUMPDETAIL_TOTALCOUNT: sort = pMemoryA->detail.totalCount - pMemoryB->detail.totalCount; break;
case ID_DUMPDETAIL_LTE16: sort = pMemoryA->detail.lte16 - pMemoryB->detail.lte16; break;
case ID_DUMPDETAIL_LTE32: sort = pMemoryA->detail.lte32 - pMemoryB->detail.lte32; break;
case ID_DUMPDETAIL_LTE128: sort = pMemoryA->detail.lte128 - pMemoryB->detail.lte128; break;
case ID_DUMPDETAIL_LTE1024: sort = pMemoryA->detail.lte1024 - pMemoryB->detail.lte1024; break;
case ID_DUMPDETAIL_GT1024: sort = pMemoryA->detail.gt1024 - pMemoryB->detail.gt1024; break; } }
// flip the sort order
if ( g_showMemDump_sortDescending ) { sort *= -1; }
return ( sort ); }
//-----------------------------------------------------------------------------
// ShowMemDump_SortItems
//
//-----------------------------------------------------------------------------
void ShowMemDump_SortItems() { LVITEM lvitem; memory_t *pMemory; int i;
if ( !g_showMemDump_hWnd ) { // only sort if window is visible
return; }
ListView_SortItems( g_showMemDump_hWndListView, ShowMemDump_CompareFunc, 0 );
memset( &lvitem, 0, sizeof( lvitem ) ); lvitem.mask = LVIF_PARAM;
// get each item and reset its list index
int itemCount = ListView_GetItemCount( g_showMemDump_hWndListView ); for ( i=0; i<itemCount; i++ ) { lvitem.iItem = i; ListView_GetItem( g_showMemDump_hWndListView, &lvitem );
pMemory = (memory_t*)lvitem.lParam; pMemory->listIndex = i; }
int count; label_t* pLabels; if ( g_showMemDump_format == FORMAT_POOLS ) { count = sizeof( g_showMemDump_PoolLabels )/sizeof( g_showMemDump_PoolLabels[0] ); pLabels = g_showMemDump_PoolLabels; } else { count = sizeof( g_showMemDump_DetailLabels )/sizeof( g_showMemDump_DetailLabels[0] ); pLabels = g_showMemDump_DetailLabels; }
// update list view columns with sort key
for ( i = 0; i < count; i++ ) { char symbol; LVCOLUMN lvc;
if ( i == g_showMemDump_sortColumn ) symbol = g_showMemDump_sortDescending ? '<' : '>'; else symbol = ' '; sprintf( pLabels[i].nameBuff, "%s %c", pLabels[i].name, symbol );
memset( &lvc, 0, sizeof( lvc ) ); lvc.mask = LVCF_TEXT; lvc.pszText = (LPSTR)pLabels[i].nameBuff;
ListView_SetColumn( g_showMemDump_hWndListView, i, &lvc ); } }
//-----------------------------------------------------------------------------
// ShowMemDump_FormatItems
//
//-----------------------------------------------------------------------------
void ShowMemDump_FormatItems() { if ( g_showMemDump_format == FORMAT_POOLS ) { for ( int i = 0; i < g_showMemDump_numMemory; i++ ) { sprintf( g_showMemDump_pMemory[i].pool.sizeBuff, "%d", g_showMemDump_pMemory[i].pool.size ); ShowMemDump_FormatSize( g_showMemDump_pMemory[i].pool.committedSize, g_showMemDump_pMemory[i].pool.committedSizeBuff, true ); } } else { for ( int i = 0; i < g_showMemDump_numMemory; i++ ) { ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.currentSize, g_showMemDump_pMemory[i].detail.currentSizeBuff, true ); ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakSize, g_showMemDump_pMemory[i].detail.peakSizeBuff, true ); ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.totalSize, g_showMemDump_pMemory[i].detail.totalSizeBuff, true ); ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.overheadSize, g_showMemDump_pMemory[i].detail.overheadSizeBuff, true ); ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakOverheadSize, g_showMemDump_pMemory[i].detail.peakOverheadSizeBuff, true ); } }
ShowMemDump_SortItems(); }
//-----------------------------------------------------------------------------
// ShowMemDump_AddViewItem
//
//-----------------------------------------------------------------------------
void ShowMemDump_AddViewItem( memory_t* pMemory ) { LVITEM lvi;
if ( !g_showMemDump_hWnd ) { // only valid if log window is visible
return; }
// update the text callback buffers
if ( g_showMemDump_format == FORMAT_POOLS ) { sprintf( pMemory->pool.sizeBuff, "%d", pMemory->pool.size ); sprintf( pMemory->pool.poolBuff, "%d", pMemory->pool.pool ); sprintf( pMemory->pool.allocatedBuff, "%d", pMemory->pool.allocated ); sprintf( pMemory->pool.freeBuff, "%d", pMemory->pool.free ); sprintf( pMemory->pool.committedBuff, "%d", pMemory->pool.committed ); ShowMemDump_FormatSize( pMemory->pool.committedSize, pMemory->pool.committedSizeBuff, true ); } else { ShowMemDump_FormatSize( pMemory->detail.currentSize, pMemory->detail.currentSizeBuff, true ); ShowMemDump_FormatSize( pMemory->detail.peakSize, pMemory->detail.peakSizeBuff, true ); ShowMemDump_FormatSize( pMemory->detail.totalSize, pMemory->detail.totalSizeBuff, true ); ShowMemDump_FormatSize( pMemory->detail.overheadSize, pMemory->detail.overheadSizeBuff, true ); ShowMemDump_FormatSize( pMemory->detail.peakOverheadSize, pMemory->detail.peakOverheadSizeBuff, true ); sprintf( pMemory->detail.timeBuff, "%d", pMemory->detail.time ); sprintf( pMemory->detail.currentCountBuff, "%d", pMemory->detail.currentCount ); sprintf( pMemory->detail.peakCountBuff, "%d", pMemory->detail.peakCount ); sprintf( pMemory->detail.totalCountBuff, "%d", pMemory->detail.totalCount ); sprintf( pMemory->detail.lte16Buff, "%d", pMemory->detail.lte16 ); sprintf( pMemory->detail.lte32Buff, "%d", pMemory->detail.lte32 ); sprintf( pMemory->detail.lte128Buff, "%d", pMemory->detail.lte128 ); sprintf( pMemory->detail.lte1024Buff, "%d", pMemory->detail.lte1024 ); sprintf( pMemory->detail.gt1024Buff, "%d", pMemory->detail.gt1024 ); }
int itemCount = ListView_GetItemCount( g_showMemDump_hWndListView );
// setup and insert at end of list
memset( &lvi, 0, sizeof( lvi ) ); lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; lvi.iItem = itemCount; lvi.iSubItem = 0; lvi.state = 0; lvi.stateMask = 0; lvi.pszText = LPSTR_TEXTCALLBACK; lvi.lParam = (LPARAM)pMemory; // insert and set the real index
pMemory->listIndex = ListView_InsertItem( g_showMemDump_hWndListView, &lvi ); }
//-----------------------------------------------------------------------------
// ShowMemDump_Refresh
//
//-----------------------------------------------------------------------------
void ShowMemDump_Refresh() { // send the command to application which replies with list data
if ( g_connectedToApp ) { ProcessCommand( "mem_dump" ); } }
//-----------------------------------------------------------------------------
// ShowMemDump_RefreshView
//
//-----------------------------------------------------------------------------
void ShowMemDump_RefreshView() { if ( strlen( g_showMemDump_currentFilename ) == 0 ) { // first time
ShowMemDump_Refresh(); return; }
// get current file
int fileSize; char *pBuffer; bool bSuccess = LoadTargetFile( g_showMemDump_currentFilename, &fileSize, (void **)&pBuffer ); if ( !bSuccess ) { // stale, try again
ShowMemDump_Refresh(); return; }
// parse and update view
ShowMemDump_Parse( pBuffer, fileSize );
Sys_Free( pBuffer ); }
//-----------------------------------------------------------------------------
// ShowMemDump_PopulateList
//
//-----------------------------------------------------------------------------
void ShowMemDump_PopulateList() { // delete previous labels
while ( 1 ) { if ( !ListView_DeleteColumn( g_showMemDump_hWndListView, 0 ) ) { break; } }
int count; label_t* pLabels; if ( g_showMemDump_format == FORMAT_POOLS ) { count = sizeof( g_showMemDump_PoolLabels )/sizeof( g_showMemDump_PoolLabels[0] ); pLabels = g_showMemDump_PoolLabels; } else { count = sizeof( g_showMemDump_DetailLabels )/sizeof( g_showMemDump_DetailLabels[0] ); pLabels = g_showMemDump_DetailLabels; }
// init list view columns
for ( int i = 0; i < count; i++ ) { LVCOLUMN lvc; memset( &lvc, 0, sizeof( lvc ) );
lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM; lvc.iSubItem = 0; lvc.cx = pLabels[i].width; lvc.fmt = LVCFMT_LEFT; lvc.pszText = ( LPSTR )pLabels[i].name;
ListView_InsertColumn( g_showMemDump_hWndListView, i, &lvc ); }
// populate list view
for ( int i = 0; i < g_showMemDump_numMemory; i++ ) { ShowMemDump_AddViewItem( &g_showMemDump_pMemory[i] ); }
ShowMemDump_SortItems(); }
//-----------------------------------------------------------------------------
// ShowMemDump_SizeWindow
//
//-----------------------------------------------------------------------------
void ShowMemDump_SizeWindow( HWND hwnd, int cx, int cy ) { if ( cx==0 || cy==0 ) { RECT rcClient; GetClientRect( hwnd, &rcClient ); cx = rcClient.right; cy = rcClient.bottom; }
// position the ListView
SetWindowPos( g_showMemDump_hWndListView, NULL, 0, 0, cx, cy, SWP_NOZORDER ); }
//-----------------------------------------------------------------------------
// ShowMemDump_WndProc
//
//-----------------------------------------------------------------------------
LRESULT CALLBACK ShowMemDump_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { WORD wID = LOWORD( wParam ); memory_t* pMemory;
switch ( message ) { case WM_CREATE: return 0L;
case WM_DESTROY: ShowMemDump_SaveConfig();
g_showMemDump_hWnd = NULL; return 0L;
case WM_INITMENU: CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_BYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_BYTES ? MF_CHECKED : MF_UNCHECKED ) ); CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_KILOBYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_KILOBYTES ? MF_CHECKED : MF_UNCHECKED ) ); CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_MEGABYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_MEGABYTES ? MF_CHECKED : MF_UNCHECKED ) ); CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_COLLAPSEOUTPUT, MF_BYCOMMAND | ( g_showMemDump_bCollapseOutput ? MF_CHECKED : MF_UNCHECKED ) ); return 0L;
case WM_SIZE: ShowMemDump_SizeWindow( hwnd, LOWORD( lParam ), HIWORD( lParam ) ); return 0L;
case WM_NOTIFY: switch ( ( ( LPNMHDR )lParam )->code ) { case LVN_COLUMNCLICK: NMLISTVIEW* pnmlv; pnmlv = ( NMLISTVIEW* )lParam; if ( g_showMemDump_sortColumn == pnmlv->iSubItem ) { // user has clicked on same column - flip the sort
g_showMemDump_sortDescending ^= 1; } else { // sort by new column
g_showMemDump_sortColumn = pnmlv->iSubItem; } ShowMemDump_SortItems(); return 0L;
case LVN_GETDISPINFO: NMLVDISPINFO* plvdi; plvdi = (NMLVDISPINFO*)lParam; pMemory = (memory_t*)plvdi->item.lParam; if ( g_showMemDump_format == FORMAT_POOLS ) { switch ( plvdi->item.iSubItem ) { case ID_DUMPPOOL_POOL: plvdi->item.pszText = pMemory->pool.poolBuff; return 0L;
case ID_DUMPPOOL_SIZE: plvdi->item.pszText = pMemory->pool.sizeBuff; return 0L;
case ID_DUMPPOOL_ALLOCATED: plvdi->item.pszText = pMemory->pool.allocatedBuff; return 0L;
case ID_DUMPPOOL_FREE: plvdi->item.pszText = pMemory->pool.freeBuff; return 0L;
case ID_DUMPPOOL_COMMITTED: plvdi->item.pszText = pMemory->pool.committedBuff; return 0L;
case ID_DUMPPOOL_COMMITTEDSIZE: plvdi->item.pszText = pMemory->pool.committedSizeBuff; return 0L; } } else { switch ( plvdi->item.iSubItem ) { case ID_DUMPDETAIL_ALLOCATION: plvdi->item.pszText = pMemory->detail.pAllocationName; return 0L; case ID_DUMPDETAIL_CURRENTSIZE: plvdi->item.pszText = pMemory->detail.currentSizeBuff; return 0L;
case ID_DUMPDETAIL_PEAKSIZE: plvdi->item.pszText = pMemory->detail.peakSizeBuff; return 0L;
case ID_DUMPDETAIL_TOTALSIZE: plvdi->item.pszText = pMemory->detail.totalSizeBuff; return 0L;
case ID_DUMPDETAIL_OVERHEAD: plvdi->item.pszText = pMemory->detail.overheadSizeBuff; return 0L;
case ID_DUMPDETAIL_PEAKOVERHEAD: plvdi->item.pszText = pMemory->detail.peakOverheadSizeBuff; return 0L;
case ID_DUMPDETAIL_TIME: plvdi->item.pszText = pMemory->detail.timeBuff; return 0L;
case ID_DUMPDETAIL_CURRENTCOUNT: plvdi->item.pszText = pMemory->detail.currentCountBuff; return 0L;
case ID_DUMPDETAIL_PEAKCOUNT: plvdi->item.pszText = pMemory->detail.peakCountBuff; return 0L;
case ID_DUMPDETAIL_TOTALCOUNT: plvdi->item.pszText = pMemory->detail.totalCountBuff; return 0L;
case ID_DUMPDETAIL_LTE16: plvdi->item.pszText = pMemory->detail.lte16Buff; return 0L;
case ID_DUMPDETAIL_LTE32: plvdi->item.pszText = pMemory->detail.lte32Buff; return 0L;
case ID_DUMPDETAIL_LTE128: plvdi->item.pszText = pMemory->detail.lte128Buff; return 0L;
case ID_DUMPDETAIL_LTE1024: plvdi->item.pszText = pMemory->detail.lte1024Buff; return 0L;
case ID_DUMPDETAIL_GT1024: plvdi->item.pszText = pMemory->detail.gt1024Buff; return 0L;
default: break; } } break; } break;
case WM_COMMAND: switch ( wID ) { case IDM_OPTIONS_REFRESH: ShowMemDump_Refresh(); return 0L;
case IDM_OPTIONS_EXPORT: ShowMemDump_Export(); return 0L;
case IDM_OPTIONS_SUMMARY: ShowMemDump_Summary(); return 0L;
case IDM_OPTIONS_BYTES: g_showMemDump_showBytes = SHOW_BYTES; ShowMemDump_FormatItems(); return 0L;
case IDM_OPTIONS_KILOBYTES: g_showMemDump_showBytes = SHOW_KILOBYTES; ShowMemDump_FormatItems(); return 0L;
case IDM_OPTIONS_MEGABYTES: g_showMemDump_showBytes = SHOW_MEGABYTES; ShowMemDump_FormatItems(); return 0L;
case IDM_OPTIONS_COLLAPSEOUTPUT: g_showMemDump_bCollapseOutput = !g_showMemDump_bCollapseOutput; ShowMemDump_RefreshView(); return 0L; } break; }
return ( DefWindowProc( hwnd, message, wParam, lParam ) ); }
//-----------------------------------------------------------------------------
// ShowMemDump_Init
//
//-----------------------------------------------------------------------------
bool ShowMemDump_Init() { // set up our window class
WNDCLASS wndclass;
memset( &wndclass, 0, sizeof( wndclass ) ); wndclass.style = 0; wndclass.lpfnWndProc = ShowMemDump_WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = g_hInstance; wndclass.hIcon = g_hIcons[ICON_APPLICATION]; wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground = g_hBackgroundBrush; wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_SHOWMEMORYDUMP ); wndclass.lpszClassName = "SHOWMEMDUMPCLASS"; if ( !RegisterClass( &wndclass ) ) return false;
ShowMemDump_LoadConfig();
return true; }
//-----------------------------------------------------------------------------
// ShowMemDump_Open
//
//-----------------------------------------------------------------------------
void ShowMemDump_Open() { RECT clientRect; HWND hWnd;
if ( g_showMemDump_hWnd ) { // only one instance
if ( IsIconic( g_showMemDump_hWnd ) ) ShowWindow( g_showMemDump_hWnd, SW_RESTORE ); SetForegroundWindow( g_showMemDump_hWnd ); return; }
hWnd = CreateWindowEx( WS_EX_CLIENTEDGE, "SHOWMEMDUMPCLASS", "", WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX, 0, 0, 700, 400, g_hDlgMain, NULL, g_hInstance, NULL ); g_showMemDump_hWnd = hWnd;
GetClientRect( g_showMemDump_hWnd, &clientRect ); hWnd = CreateWindow( WC_LISTVIEW, "", WS_VISIBLE|WS_CHILD|LVS_REPORT, 0, 0, clientRect.right-clientRect.left, clientRect.bottom-clientRect.top, g_showMemDump_hWnd, ( HMENU )ID_SHOWMEMDUMP_LISTVIEW, g_hInstance, NULL ); g_showMemDump_hWndListView = hWnd;
ListView_SetBkColor( g_showMemDump_hWndListView, g_backgroundColor ); ListView_SetTextBkColor( g_showMemDump_hWndListView, g_backgroundColor );
DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP; ListView_SetExtendedListViewStyleEx( g_showMemDump_hWndListView, style, style );
ShowMemDump_PopulateList();
ShowMemDump_SetTitle();
if ( g_showMemDump_windowRect.right && g_showMemDump_windowRect.bottom ) MoveWindow( g_showMemDump_hWnd, g_showMemDump_windowRect.left, g_showMemDump_windowRect.top, g_showMemDump_windowRect.right-g_showMemDump_windowRect.left, g_showMemDump_windowRect.bottom-g_showMemDump_windowRect.top, FALSE ); ShowWindow( g_showMemDump_hWnd, SHOW_OPENWINDOW );
// get data from application
ShowMemDump_Refresh(); }
//-----------------------------------------------------------------------------
// MatchAllocationName
//
//-----------------------------------------------------------------------------
void MatchAllocationName( memory_t *&pMemory ) { memory_t *curEntry = g_showMemDump_pMemory; for ( int i=0; i<g_showMemDump_numMemory; ++i ) { if ( !strcmp( curEntry->detail.pAllocationName, pMemory->detail.pAllocationName ) ) { pMemory = curEntry; return; } ++curEntry; } }
//-----------------------------------------------------------------------------
// ShowMemDump_Parse
//
//-----------------------------------------------------------------------------
void ShowMemDump_Parse( const char *pBuffer, int fileSize ) { char *ptr; char *pToken; char *pLineStart; int numLines; int size; memory_t *pMemory;
// remove old entries
ShowMemDump_Clear(); if ( !pBuffer || !fileSize ) { // no valid data
return; }
Sys_SetScriptData( pBuffer, fileSize );
// skip first line, column headers
Sys_SkipRestOfLine();
Sys_SaveParser();
// count lines
numLines = 0; while ( 1 ) { pToken = Sys_GetToken( true ); if ( !pToken || !pToken[0] ) break; numLines++; Sys_SkipRestOfLine(); }
// each line represents one complete entry
g_showMemDump_pMemory = (memory_t *)Sys_Alloc( numLines * sizeof( memory_t ) );
Sys_RestoreParser();
pMemory = g_showMemDump_pMemory;
int format = 0; if ( !V_strnicmp( g_sys_scriptptr, "pool ", 5 ) ) { // parse as pool stats
format = FORMAT_POOLS;
while ( 1 ) { // find start of relevant data
bool bFound = false; while ( 1 ) { pToken = Sys_GetToken( true ); if ( !pToken || !pToken[0] ) break; if ( !V_stricmp( pToken, "size:" ) ) { bFound = true; break; } } if ( !bFound ) { break; }
memset( pMemory, 0, sizeof( memory_t ) );
pMemory->pool.pool = g_showMemDump_numMemory;
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->pool.size = atoi( pToken );
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; if ( !V_stricmp( pToken, "allocated:" ) ) { pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->pool.allocated = atoi( pToken ); } else { break; }
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; if ( !V_stricmp( pToken, "free:" ) ) { pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->pool.free = atoi( pToken ); } else { break; }
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; if ( !V_stricmp( pToken, "committed:" ) ) { pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->pool.committed = atoi( pToken ); } else { break; }
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; if ( !V_stricmp( pToken, "committedsize:" ) ) { pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->pool.committedSize = atoi( pToken ); } else { break; }
pMemory++; g_showMemDump_numMemory++; if ( g_showMemDump_numMemory >= numLines ) break; } } else { // parse as detail stats
format = FORMAT_DETAILS;
while ( 1 ) { pLineStart = g_sys_scriptptr; // can't tokenize, find start of parsable data
ptr = V_stristr( g_sys_scriptptr, ", line " ); if ( !ptr ) break; g_sys_scriptptr = ptr + strlen( ", line " );
// advance past the expected line number
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break;
if ( !g_showMemDump_bCollapseOutput ) { size = g_sys_scriptptr-pLineStart; } else { size = ptr-pLineStart; }
memset( pMemory, 0, sizeof(memory_t) ); memory_t *pCurRecordStart = pMemory;
pMemory->detail.pAllocationName = new char[size+1]; memcpy( pMemory->detail.pAllocationName, pLineStart, size ); pMemory->detail.pAllocationName[size] = '\0'; Sys_NormalizePath( pMemory->detail.pAllocationName, false );
if ( g_showMemDump_bCollapseOutput ) { MatchAllocationName( pMemory ); }
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.currentSize += (int)(1024.0f*atof( pToken ));
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.peakSize += (int)(1024.0f*atof( pToken ));
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.totalSize += (int)(1024.0f*atof( pToken ));
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.overheadSize += (int)(1024.0f*atof( pToken ));
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.peakOverheadSize += (int)(1024.0f*atof( pToken ));
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.time += atoi( pToken );
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.currentCount += atoi( pToken );
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.peakCount += atoi( pToken );
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.totalCount += atoi( pToken );
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.lte16 += atoi( pToken );
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.lte32 += atoi( pToken );
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.lte128 += atoi( pToken );
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.lte1024 += atoi( pToken );
pToken = Sys_GetToken( false ); if ( !pToken || !pToken[0] ) break; pMemory->detail.gt1024 += atoi( pToken );
Sys_SkipRestOfLine();
if( pMemory == pCurRecordStart ) { pMemory++; g_showMemDump_numMemory++; } else { pMemory = pCurRecordStart; }
if ( g_showMemDump_numMemory >= numLines ) break; } }
if ( g_showMemDump_format != format ) { // format change will cause list view change
g_showMemDump_format = format; g_showMemDump_sortColumn = 0; g_showMemDump_sortDescending = 0; }
ShowMemDump_PopulateList(); }
//-----------------------------------------------------------------------------
// rc_MemDump
//
// Sent from application with memory dump file
//-----------------------------------------------------------------------------
int rc_MemDump( char *pCommand ) { char* pToken; int retVal; int errCode = -1; int fileSize; char *pBuffer;
// get name of file
pToken = GetToken( &pCommand ); if ( !pToken[0] ) goto cleanUp;
// get file
strcpy( g_showMemDump_currentFilename, pToken ); retVal = LoadTargetFile( g_showMemDump_currentFilename, &fileSize, (void **)&pBuffer );
DebugCommand( "0x%8.8x = MemDump( %s )\n", retVal, g_showMemDump_currentFilename );
// parse and update view
ShowMemDump_Parse( pBuffer, fileSize );
Sys_Free( pBuffer );
// success
errCode = 0;
cleanUp: return ( errCode ); }
|