126 lines
3.7 KiB
C++
126 lines
3.7 KiB
C++
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// 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 ) )
|