You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
561 lines
14 KiB
561 lines
14 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// MEM_PROFILE.CPP |
|
// |
|
// Memory Profiling Display |
|
//=====================================================================================// |
|
#include "vxconsole.h" |
|
|
|
#define PROFILE_MAXSAMPLES 512 |
|
#define PROFILE_MEMORYHEIGHT 100 |
|
#define PROFILE_NUMMINORTICKS 3 |
|
#define PROFILE_LABELWIDTH 50 |
|
#define PROFILE_SCALESTEPS 8 |
|
#define PROFILE_MINSCALE 0.2f |
|
#define PROFILE_MAXSCALE 3.0f |
|
#define PROFILE_NUMMINORTICKS 3 |
|
#define PROFILE_MAJORTICKMB 16 |
|
#define PROFILE_WARNINGMB 10 |
|
#define PROFILE_SEVEREMB 5 |
|
|
|
#define ID_MEMPROFILE 1 |
|
|
|
HWND g_memProfile_hWnd; |
|
RECT g_memProfile_WindowRect; |
|
int g_memProfile_tickMarks; |
|
int g_memProfile_colors; |
|
int g_memProfile_scale; |
|
UINT_PTR g_memProfile_Timer; |
|
int g_memProfile_numSamples; |
|
int g_memProfile_samples[PROFILE_MAXSAMPLES]; |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_SaveConfig |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_SaveConfig() |
|
{ |
|
char buff[256]; |
|
WINDOWPLACEMENT wp; |
|
|
|
// profile history |
|
if ( g_memProfile_hWnd ) |
|
{ |
|
memset( &wp, 0, sizeof( wp ) ); |
|
wp.length = sizeof( WINDOWPLACEMENT ); |
|
GetWindowPlacement( g_memProfile_hWnd, &wp ); |
|
g_memProfile_WindowRect = wp.rcNormalPosition; |
|
sprintf( buff, "%d %d %d %d", wp.rcNormalPosition.left, wp.rcNormalPosition.top, wp.rcNormalPosition.right, wp.rcNormalPosition.bottom ); |
|
Sys_SetRegistryString( "MemProfileWindowRect", buff ); |
|
} |
|
|
|
Sys_SetRegistryInteger( "MemProfileScale", g_memProfile_scale ); |
|
Sys_SetRegistryInteger( "MemProfileTickMarks", g_memProfile_tickMarks ); |
|
Sys_SetRegistryInteger( "MemProfileColors", g_memProfile_colors ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_LoadConfig |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_LoadConfig() |
|
{ |
|
int numArgs; |
|
char buff[256]; |
|
|
|
// profile history |
|
Sys_GetRegistryString( "MemProfileWindowRect", buff, "", sizeof( buff ) ); |
|
numArgs = sscanf( buff, "%d %d %d %d", &g_memProfile_WindowRect.left, &g_memProfile_WindowRect.top, &g_memProfile_WindowRect.right, &g_memProfile_WindowRect.bottom ); |
|
if ( numArgs != 4 ) |
|
{ |
|
memset( &g_memProfile_WindowRect, 0, sizeof( g_memProfile_WindowRect ) ); |
|
} |
|
|
|
Sys_GetRegistryInteger( "MemProfileScale", 0, g_memProfile_scale ); |
|
if ( g_memProfile_scale < -PROFILE_SCALESTEPS || g_memProfile_scale > PROFILE_SCALESTEPS ) |
|
{ |
|
g_memProfile_scale = 0; |
|
} |
|
|
|
Sys_GetRegistryInteger( "MemProfileTickMarks", 1, g_memProfile_tickMarks ); |
|
Sys_GetRegistryInteger( "MemProfileColors", 1, g_memProfile_colors ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_SetTitle |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_SetTitle() |
|
{ |
|
char titleBuff[128]; |
|
|
|
if ( g_memProfile_hWnd ) |
|
{ |
|
strcpy( titleBuff, "Free Memory Available" ); |
|
if ( g_memProfile_Timer ) |
|
{ |
|
strcat( titleBuff, " [ON]" ); |
|
} |
|
|
|
SetWindowText( g_memProfile_hWnd, titleBuff ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_EnableProfiling |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_EnableProfiling( bool bEnable ) |
|
{ |
|
if ( !g_memProfile_hWnd ) |
|
{ |
|
return; |
|
} |
|
|
|
UINT_PTR timer = TIMERID_MEMPROFILE; |
|
if ( bEnable && !g_memProfile_Timer ) |
|
{ |
|
// run at 10Hz |
|
g_memProfile_Timer = SetTimer( g_memProfile_hWnd, timer, 100, NULL ); |
|
} |
|
else if ( !bEnable && g_memProfile_Timer ) |
|
{ |
|
KillTimer( g_memProfile_hWnd, timer ); |
|
g_memProfile_Timer = NULL; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_UpdateWindow |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_UpdateWindow() |
|
{ |
|
if ( g_memProfile_hWnd && !IsIconic( g_memProfile_hWnd ) ) |
|
{ |
|
// visible - force a client repaint |
|
InvalidateRect( g_memProfile_hWnd, NULL, true ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// rc_FreeMemory |
|
// |
|
//----------------------------------------------------------------------------- |
|
int rc_FreeMemory( char* commandPtr ) |
|
{ |
|
int errCode = -1; |
|
int freeMemory; |
|
|
|
char *cmdToken = GetToken( &commandPtr ); |
|
if ( !cmdToken[0] ) |
|
{ |
|
goto cleanUp; |
|
} |
|
sscanf( cmdToken, "%x", &freeMemory ); |
|
|
|
g_memProfile_samples[g_memProfile_numSamples % PROFILE_MAXSAMPLES] = freeMemory; |
|
g_memProfile_numSamples++; |
|
|
|
DebugCommand( "FreeMemory( 0x%8.8x )\n", freeMemory ); |
|
|
|
MemProfile_UpdateWindow(); |
|
|
|
// success |
|
errCode = 0; |
|
|
|
cleanUp: |
|
return ( errCode ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_ZoomIn |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_ZoomIn( int& scale, int numSteps ) |
|
{ |
|
scale++; |
|
if ( scale > numSteps ) |
|
{ |
|
scale = numSteps; |
|
return; |
|
} |
|
MemProfile_UpdateWindow(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_ZoomOut |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_ZoomOut( int& scale, int numSteps ) |
|
{ |
|
scale--; |
|
if ( scale < -numSteps ) |
|
{ |
|
scale = -numSteps; |
|
return; |
|
} |
|
MemProfile_UpdateWindow(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_CalcScale |
|
// |
|
//----------------------------------------------------------------------------- |
|
float MemProfile_CalcScale( int scale, int numSteps, float min, float max ) |
|
{ |
|
float t; |
|
|
|
// from integral scale [-numSteps..numSteps] to float scale [min..max] |
|
t = ( float )( scale + numSteps )/( float )( 2*numSteps ); |
|
t = min + t*( max-min ); |
|
|
|
return t; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_Draw |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_Draw( HDC hdc, RECT* clientRect ) |
|
{ |
|
char labelBuff[128]; |
|
HPEN hBlackPen; |
|
HPEN hPenOld; |
|
HPEN hNullPen; |
|
HPEN hGreyPen; |
|
HBRUSH hColoredBrush; |
|
HBRUSH hBrushOld; |
|
HFONT hFontOld; |
|
int currentSample; |
|
int numTicks; |
|
int memoryHeight; |
|
int windowWidth; |
|
int windowHeight; |
|
int x; |
|
int y; |
|
int y0; |
|
int i; |
|
int j; |
|
int h; |
|
int numbars; |
|
RECT rect; |
|
float t; |
|
float scale; |
|
|
|
hBlackPen = CreatePen( PS_SOLID, 1, RGB( 0,0,0 ) ); |
|
hGreyPen = CreatePen( PS_SOLID, 1, Sys_ColorScale( g_backgroundColor, 0.85f ) ); |
|
hNullPen = CreatePen( PS_NULL, 0, RGB( 0,0,0 ) ); |
|
hPenOld = ( HPEN )SelectObject( hdc, hBlackPen ); |
|
hFontOld = SelectFont( hdc, g_hProportionalFont ); |
|
|
|
// zoom |
|
scale = MemProfile_CalcScale( g_memProfile_scale, PROFILE_SCALESTEPS, PROFILE_MINSCALE, PROFILE_MAXSCALE ); |
|
memoryHeight = ( int )( PROFILE_MEMORYHEIGHT*scale ); |
|
windowWidth = clientRect->right-clientRect->left; |
|
windowHeight = clientRect->bottom-clientRect->top; |
|
|
|
numTicks = windowHeight/memoryHeight + 2; |
|
if ( numTicks < 0 ) |
|
{ |
|
numTicks = 1; |
|
} |
|
else if ( numTicks > 512/PROFILE_MAJORTICKMB + 1 ) |
|
{ |
|
numTicks = 512/PROFILE_MAJORTICKMB + 1; |
|
} |
|
|
|
SetBkColor( hdc, g_backgroundColor ); |
|
|
|
x = 0; |
|
y = windowHeight; |
|
for ( i=0; i<numTicks; i++ ) |
|
{ |
|
// major ticks |
|
SelectObject( hdc, hBlackPen ); |
|
MoveToEx( hdc, 0, y, NULL ); |
|
LineTo( hdc, windowWidth, y ); |
|
|
|
if ( g_memProfile_tickMarks ) |
|
{ |
|
// could be very zoomed out, gap must be enough for label, otherwise don't draw |
|
int gapY = memoryHeight/( PROFILE_NUMMINORTICKS+1 ); |
|
if ( gapY >= 10 ) |
|
{ |
|
// minor ticks |
|
y0 = y; |
|
SelectObject( hdc, hGreyPen ); |
|
for ( j=0; j<PROFILE_NUMMINORTICKS; j++ ) |
|
{ |
|
y0 += gapY; |
|
MoveToEx( hdc, 0, y0, NULL ); |
|
LineTo( hdc, windowWidth, y0 ); |
|
} |
|
} |
|
} |
|
|
|
// tick labels |
|
if ( i ) |
|
{ |
|
rect.left = windowWidth - 50; |
|
rect.right = windowWidth; |
|
rect.top = y - 20; |
|
rect.bottom = y; |
|
sprintf( labelBuff, "%d MB", i*PROFILE_MAJORTICKMB ); |
|
DrawText( hdc, labelBuff, -1, &rect, DT_RIGHT|DT_SINGLELINE|DT_BOTTOM ); |
|
} |
|
|
|
y -= memoryHeight; |
|
} |
|
|
|
// vertical bars |
|
if ( g_memProfile_numSamples ) |
|
{ |
|
SelectObject( hdc, hNullPen ); |
|
|
|
numbars = windowWidth-PROFILE_LABELWIDTH; |
|
currentSample = g_memProfile_numSamples-1; |
|
for ( x=numbars-1; x>=0; x-=4 ) |
|
{ |
|
float sample = g_memProfile_samples[currentSample % PROFILE_MAXSAMPLES]/( 1024.0f * 1024.0f ); |
|
|
|
y = windowHeight; |
|
t = sample/(float)PROFILE_MAJORTICKMB; |
|
h = ( int )( t * ( float )memoryHeight ); |
|
if ( h ) |
|
{ |
|
if ( h > windowHeight ) |
|
h = windowHeight; |
|
|
|
COLORREF barColor; |
|
if ( sample >= PROFILE_WARNINGMB ) |
|
{ |
|
barColor = RGB( 100, 255, 100 ); |
|
} |
|
else if ( sample >= PROFILE_SEVEREMB ) |
|
{ |
|
barColor = RGB( 255, 255, 100 ); |
|
} |
|
else |
|
{ |
|
barColor = RGB( 255, 0, 0 ); |
|
} |
|
|
|
hColoredBrush = CreateSolidBrush( g_memProfile_colors ? barColor : RGB( 80, 80, 80 ) ); |
|
hBrushOld = ( HBRUSH )SelectObject( hdc, hColoredBrush ); |
|
|
|
Rectangle( hdc, x-4, y-h, x, y+1 ); |
|
y -= h; |
|
|
|
SelectObject( hdc, hBrushOld ); |
|
DeleteObject( hColoredBrush ); |
|
} |
|
|
|
currentSample--; |
|
if ( currentSample < 0 ) |
|
{ |
|
// no data |
|
break; |
|
} |
|
} |
|
} |
|
|
|
SelectObject( hdc, hFontOld ); |
|
SelectObject( hdc, hPenOld ); |
|
DeleteObject( hBlackPen ); |
|
DeleteObject( hGreyPen ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_TimerProc |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_TimerProc( HWND hwnd, UINT_PTR idEvent ) |
|
{ |
|
static bool busy = false; |
|
|
|
if ( busy ) |
|
{ |
|
return; |
|
} |
|
|
|
busy = true; |
|
|
|
if ( g_connectedToApp ) |
|
{ |
|
// send as async |
|
DmAPI_SendCommand( VXCONSOLE_COMMAND_PREFIX "!" "__memory__ quiet", false ); |
|
} |
|
|
|
busy = false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_WndProc |
|
// |
|
//----------------------------------------------------------------------------- |
|
LRESULT CALLBACK MemProfile_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) |
|
{ |
|
WORD wID = LOWORD( wParam ); |
|
HDC hdc; |
|
PAINTSTRUCT ps; |
|
RECT rect; |
|
CREATESTRUCT *createStructPtr; |
|
|
|
switch ( message ) |
|
{ |
|
case WM_CREATE: |
|
// set the window identifier |
|
createStructPtr = ( CREATESTRUCT* )lParam; |
|
SetWindowLong( hwnd, GWL_USERDATA+0, ( LONG )createStructPtr->lpCreateParams ); |
|
|
|
// clear samples |
|
g_memProfile_numSamples = 0; |
|
memset( g_memProfile_samples, 0, sizeof( g_memProfile_samples ) ); |
|
return 0L; |
|
|
|
case WM_DESTROY: |
|
MemProfile_SaveConfig(); |
|
MemProfile_EnableProfiling( false ); |
|
g_memProfile_hWnd = NULL; |
|
return 0L; |
|
|
|
case WM_INITMENU: |
|
CheckMenuItem( ( HMENU )wParam, IDM_MEMPROFILE_TICKMARKS, MF_BYCOMMAND | ( g_memProfile_tickMarks ? MF_CHECKED : MF_UNCHECKED ) ); |
|
CheckMenuItem( ( HMENU )wParam, IDM_MEMPROFILE_COLORS, MF_BYCOMMAND | ( g_memProfile_colors ? MF_CHECKED : MF_UNCHECKED ) ); |
|
CheckMenuItem( ( HMENU )wParam, IDM_MEMPROFILE_ENABLE, MF_BYCOMMAND | ( g_memProfile_Timer != NULL ? MF_CHECKED : MF_UNCHECKED ) ); |
|
return 0L; |
|
|
|
case WM_PAINT: |
|
GetClientRect( hwnd, &rect ); |
|
hdc = BeginPaint( hwnd, &ps ); |
|
MemProfile_Draw( hdc, &rect ); |
|
EndPaint( hwnd, &ps ); |
|
return 0L; |
|
|
|
case WM_SIZE: |
|
// force a redraw |
|
MemProfile_UpdateWindow(); |
|
return 0L; |
|
|
|
case WM_TIMER: |
|
if ( wID == TIMERID_MEMPROFILE ) |
|
{ |
|
MemProfile_TimerProc( hwnd, TIMERID_MEMPROFILE ); |
|
return 0L; |
|
} |
|
break; |
|
|
|
case WM_KEYDOWN: |
|
switch ( wParam ) |
|
{ |
|
case VK_INSERT: |
|
MemProfile_ZoomIn( g_memProfile_scale, PROFILE_SCALESTEPS ); |
|
return 0L; |
|
|
|
case VK_DELETE: |
|
MemProfile_ZoomOut( g_memProfile_scale, PROFILE_SCALESTEPS ); |
|
return 0L; |
|
} |
|
break; |
|
|
|
case WM_COMMAND: |
|
switch ( wID ) |
|
{ |
|
case IDM_MEMPROFILE_TICKMARKS: |
|
g_memProfile_tickMarks ^= 1; |
|
MemProfile_UpdateWindow(); |
|
return 0L; |
|
|
|
case IDM_MEMPROFILE_COLORS: |
|
g_memProfile_colors ^= 1; |
|
MemProfile_UpdateWindow(); |
|
return 0L; |
|
|
|
case IDM_MEMPROFILE_ZOOMIN: |
|
MemProfile_ZoomIn( g_memProfile_scale, PROFILE_SCALESTEPS ); |
|
return 0L; |
|
|
|
case IDM_MEMPROFILE_ZOOMOUT: |
|
MemProfile_ZoomOut( g_memProfile_scale, PROFILE_SCALESTEPS ); |
|
return 0L; |
|
|
|
case IDM_MEMPROFILE_ENABLE: |
|
bool bEnable = ( g_memProfile_Timer != NULL ); |
|
bEnable ^= 1; |
|
MemProfile_EnableProfiling( bEnable ); |
|
MemProfile_SetTitle(); |
|
return 0L; |
|
} |
|
break; |
|
} |
|
return ( DefWindowProc( hwnd, message, wParam, lParam ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_Open |
|
// |
|
//----------------------------------------------------------------------------- |
|
void MemProfile_Open() |
|
{ |
|
HWND hWnd; |
|
|
|
if ( g_memProfile_hWnd ) |
|
{ |
|
// only one profile instance |
|
if ( IsIconic( g_memProfile_hWnd ) ) |
|
ShowWindow( g_memProfile_hWnd, SW_RESTORE ); |
|
SetForegroundWindow( g_memProfile_hWnd ); |
|
return; |
|
} |
|
|
|
hWnd = CreateWindowEx( |
|
WS_EX_CLIENTEDGE, |
|
"MEMPROFILECLASS", |
|
"", |
|
WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX, |
|
0, |
|
0, |
|
600, |
|
500, |
|
g_hDlgMain, |
|
NULL, |
|
g_hInstance, |
|
( void* )ID_MEMPROFILE ); |
|
g_memProfile_hWnd = hWnd; |
|
|
|
MemProfile_EnableProfiling( true ); |
|
MemProfile_SetTitle(); |
|
|
|
if ( g_memProfile_WindowRect.right && g_memProfile_WindowRect.bottom ) |
|
MoveWindow( g_memProfile_hWnd, g_memProfile_WindowRect.left, g_memProfile_WindowRect.top, g_memProfile_WindowRect.right-g_memProfile_WindowRect.left, g_memProfile_WindowRect.bottom-g_memProfile_WindowRect.top, FALSE ); |
|
ShowWindow( g_memProfile_hWnd, SHOW_OPENWINDOW ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// MemProfile_Init |
|
// |
|
//----------------------------------------------------------------------------- |
|
bool MemProfile_Init() |
|
{ |
|
WNDCLASS wndclass; |
|
|
|
// set up our window class |
|
memset( &wndclass, 0, sizeof( wndclass ) ); |
|
wndclass.style = 0; |
|
wndclass.lpfnWndProc = MemProfile_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_MEMPROFILE ); |
|
wndclass.lpszClassName = "MEMPROFILECLASS"; |
|
if ( !RegisterClass( &wndclass ) ) |
|
return false; |
|
|
|
MemProfile_LoadConfig(); |
|
|
|
return true; |
|
}
|
|
|