2025-05-17 14:17:42 -04:00
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
2010-07-22 01:46:14 -05:00
//
// Purpose: See c_memorylog.h
//
//=============================================================================//
# include "cbase.h"
# include "inetchannelinfo.h"
# include "clientterrorplayer.h"
# include "c_memorylog.h"
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
# if ( defined( _X360 ) && !defined( _CERT ) )
ConVar memorylog_tick ( " memorylog_tick " , " 20 " , FCVAR_CHEAT , " Set to N to spew free memory to the console every N seconds to be captured by logging (0 disables) . " ) ;
ConVar memorylog_mem_dump ( " memorylog_mem_dump " , " 0 " , FCVAR_CHEAT ) ;
// Memory log auto game system instantiation
C_MemoryLog g_MemoryLog ;
bool C_MemoryLog : : Init ( void )
{
// Spew on the first frame after init
m_fLastSpewTime = - memorylog_tick . GetFloat ( ) ;
// Set up a string we can search for in full heap crashdumps:
memset ( m_nRecentFreeMem , 0 , sizeof ( m_nRecentFreeMem ) ) ;
memcpy ( m_nRecentFreeMem , " maryhadatinylamb " , 16 ) ;
return true ;
}
void C_MemoryLog : : Spew ( void )
{
// Spew "date+time | free mem | listen/not | map | bots | players", so we can
// use console logs to correlate memory leaks with playtest patterns.
if ( memorylog_tick . GetFloat ( ) < = 0 )
return ; // Disabled
int time = ( int ) ( Plat_FloatTime ( ) + 0.5f ) ;
MEMORYSTATUS memStats ;
GlobalMemoryStatus ( & memStats ) ;
int freeMem = memStats . dwAvailPhys ;
// Determine if this machine is the server
INetChannelInfo * pNetInfo = engine - > GetNetChannelInfo ( ) ;
bool listen = ( pNetInfo & & ( pNetInfo - > IsLoopback ( ) | | V_strstr ( pNetInfo - > GetAddress ( ) , " 127.0.0.1 " ) ) ) ;
char mapName [ 32 ] = " " ;
if ( engine - > GetLevelNameShort ( ) )
V_strncpy ( mapName , engine - > GetLevelNameShort ( ) , sizeof ( mapName ) ) ;
if ( ! mapName [ 0 ] )
V_strncpy ( mapName , " none " , sizeof ( mapName ) ) ;
char playerNames [ 512 ] = " " ;
int numBots = 0 ;
int numPlayers = 0 ;
for ( int i = 1 ; i < = gpGlobals - > maxClients ; i + + )
{
player_info_s playerInfo ;
C_TerrorPlayer * player = static_cast < C_TerrorPlayer * > ( UTIL_PlayerByIndex ( i ) ) ;
if ( player & & player - > IsPlayer ( ) & & engine - > GetPlayerInfo ( i , & playerInfo ) )
{
if ( playerInfo . fakeplayer )
{
// Ignore zombie bots
if ( player - > GetCharacter ( ) < NUM_SURVIVOR_CHARACTERS )
numBots + + ;
}
else
{
char playerName [ 64 ] ;
V_snprintf ( playerName , sizeof ( playerName ) , " , %s%s%s " ,
playerInfo . name ,
player - > IsObserver ( ) ? " |SPEC " : " " ,
C_BasePlayer : : IsLocalPlayer ( player ) ? " |LOCAL " : " " ) ;
V_strcat ( playerNames , playerName , sizeof ( playerNames ) ) ;
numPlayers + + ;
}
}
}
ConMsg ( " [MEMORYLOG] Time:%6d | Free: %6.2f | %s | Map: %-32s | Bots: %2d | Players: %2d%s \n " ,
time ,
freeMem / ( 1024.0f * 1024.0f ) ,
listen ? " Server " : " Client " ,
mapName ,
numBots , numPlayers , playerNames ) ;
// Keep the last N free memory values in an array, for inspection in full heap crashdumps
for ( int i = 255 ; i > 4 ; i - - ) m_nRecentFreeMem [ i ] = m_nRecentFreeMem [ i - 1 ] ;
m_nRecentFreeMem [ 4 ] = freeMem ;
if ( memorylog_mem_dump . GetBool ( ) )
{
g_pMemAlloc - > DumpStats ( ) ;
}
}
void C_MemoryLog : : Update ( float frametime )
{
float curTime = Plat_FloatTime ( ) ;
if ( ( curTime - m_fLastSpewTime ) > = memorylog_tick . GetFloat ( ) )
{
m_fLastSpewTime = curTime ;
Spew ( ) ;
}
}
void C_MemoryLog : : LevelInitPostEntity ( void )
{
// Spew on the first frame after map load
m_fLastSpewTime = - memorylog_tick . GetFloat ( ) ;
}
void C_MemoryLog : : LevelShutdownPreEntity ( void )
{
// Spew in case we don't make it to the next map
Spew ( ) ;
}
# endif // ( defined( _X360 ) && !defined( _CERT ) )