diff options
Diffstat (limited to 'engine/dt_instrumentation_server.cpp')
| -rw-r--r-- | engine/dt_instrumentation_server.cpp | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/engine/dt_instrumentation_server.cpp b/engine/dt_instrumentation_server.cpp new file mode 100644 index 0000000..f1ebff9 --- /dev/null +++ b/engine/dt_instrumentation_server.cpp @@ -0,0 +1,357 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "filesystem_engine.h" +#include "filesystem.h" +#include "dt_instrumentation_server.h" +#include "dt_send.h" +#include "tier1/utlstring.h" +#include "utllinkedlist.h" +#include "dt.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define DELTA_DISTANCE_BAND 200 +#define NUM_DELTA_DISTANCE_BANDS (8000/DELTA_DISTANCE_BAND) + + +// Data we track per SendTable on the server. +class CDTISendTable +{ +public: + // Which SendTable we're interested in. + CUtlString m_NetTableName; + + // How many cycles we've spent in certain calls. + CCycleCount m_nCalcDeltaCycles; + int m_nCalcDeltaCalls; + + CCycleCount m_nEncodeCycles; + int m_nEncodeCalls; + + CCycleCount m_nShouldTransmitCycles; + int m_nShouldTransmitCalls; + + CCycleCount m_nWriteDeltaPropsCycles; + + // Used to determine how much the class uses manual mode. + int m_nChangeAutoDetects; + int m_nNoChanges; + + // Set to false if no events were recorded for this class. + bool HadAnyAction() const { return m_nCalcDeltaCalls || m_nEncodeCalls || m_nShouldTransmitCalls; } + + // This tracks how many times an entity was delta'd for each distance from a client. + unsigned short m_DistanceDeltaCounts[NUM_DELTA_DISTANCE_BANDS]; +}; + + +static CCycleCount g_TotalServerDTICycles; + +static CUtlLinkedList<CDTISendTable*, unsigned short> g_DTISendTables; + +bool g_bServerDTIEnabled = false; +static char const *g_pServerDTIFilename = 0; + +static bool g_bFirstHookTimer = true; +static CCycleCount g_ServerDTITimer; + + + +void ServerDTI_Init( char const *pFilename ) +{ + g_pServerDTIFilename = pFilename; + g_bServerDTIEnabled = true; + g_TotalServerDTICycles.Init(); + g_bFirstHookTimer = true; +} + + +void ServerDTI_Term() +{ + if ( !g_pServerDTIFilename ) + return; + ServerDTI_Flush(); + g_DTISendTables.PurgeAndDeleteElements(); + g_pServerDTIFilename = 0; + g_bServerDTIEnabled = false; +} + + +void ServerDTI_Flush() +{ + if ( !g_pServerDTIFilename ) + return; + + CCycleCount curTime; + curTime.Sample(); + + CCycleCount runningTime; + CCycleCount::Sub( curTime, g_ServerDTITimer, runningTime ); + + // Write out a file that can be used by Excel. + FileHandle_t fp = g_pFileSystem->Open( g_pServerDTIFilename, "wt", "LOGDIR" ); + + if( fp != FILESYSTEM_INVALID_HANDLE ) + { + // Write the header. + g_pFileSystem->FPrintf( fp, + "DTName" + + "\tCalcDelta calls" + "\tCalcDelta ms" + + "\tEncode calls" + "\tEncode ms" + + "\tShouldTransmit calls" + "\tShouldTransmit ms" + + "\tWriteDeltaProps ms" + + "\t%% manual mode" + + "\tTotal" + "\tPercent" + "\n" + ); + + // Calculate totals. + CCycleCount totalCalcDelta, totalEncode, totalShouldTransmit, totalDeltaProps; + totalCalcDelta.Init(); + totalEncode.Init(); + totalShouldTransmit.Init(); + + FOR_EACH_LL( g_DTISendTables, i ) + { + CDTISendTable *pTable = g_DTISendTables[i]; + + CCycleCount::Add( pTable->m_nCalcDeltaCycles, totalCalcDelta, totalCalcDelta ); + CCycleCount::Add( pTable->m_nEncodeCycles, totalEncode, totalEncode ); + CCycleCount::Add( pTable->m_nShouldTransmitCycles, totalShouldTransmit, totalShouldTransmit ); + CCycleCount::Add( pTable->m_nWriteDeltaPropsCycles, totalDeltaProps, totalDeltaProps ); + } + + + FOR_EACH_LL( g_DTISendTables, j ) + { + CDTISendTable *pTable = g_DTISendTables[j]; + + if ( !pTable->HadAnyAction() ) + continue; + + CCycleCount total; + CCycleCount::Add( pTable->m_nEncodeCycles, pTable->m_nCalcDeltaCycles, total ); + CCycleCount::Add( pTable->m_nShouldTransmitCycles, total, total ); + + g_pFileSystem->FPrintf( fp, + "%s" + + "\t%d" + "\t%.3f" + + "\t%d" + "\t%.3f" + + "\t%d" + "\t%.3f" + + "\t%.3f" + + "\t%.2f" + + "\t%.3f" + "\t%.3f" + "\n", + pTable->m_NetTableName.String(), + + pTable->m_nCalcDeltaCalls, + pTable->m_nCalcDeltaCycles.GetMillisecondsF(), + + pTable->m_nEncodeCalls, + pTable->m_nEncodeCycles.GetMillisecondsF(), + + pTable->m_nShouldTransmitCalls, + pTable->m_nShouldTransmitCycles.GetMillisecondsF(), + + pTable->m_nWriteDeltaPropsCycles.GetMillisecondsF(), + + (float)pTable->m_nNoChanges * 100.0f / (pTable->m_nNoChanges + pTable->m_nChangeAutoDetects), + + total.GetMillisecondsF(), + total.GetMillisecondsF() * 100 / runningTime.GetMillisecondsF() + ); + } + + g_pFileSystem->FPrintf( fp, "\n\n" ); + + g_pFileSystem->FPrintf( fp, + "Total profile ms:" + "\t%.3f\n", + runningTime.GetMillisecondsF() + ); + + g_pFileSystem->FPrintf( fp, + "Total CalcDelta ms:" + "\t%.3f" + "\tPercent:" + "\t%.3f\n", + totalCalcDelta.GetMillisecondsF(), + totalCalcDelta.GetMillisecondsF() * 100.0 / runningTime.GetMillisecondsF() + ); + + g_pFileSystem->FPrintf( fp, + "Total Encode ms:" + "\t%.3f" + "\tPercent:" + "\t%.3f\n", + totalEncode.GetMillisecondsF(), + totalEncode.GetMillisecondsF() * 100.0 / runningTime.GetMillisecondsF() + ); + + g_pFileSystem->FPrintf( fp, + "Total ShouldTransmit ms:" + "\t%.3f" + "\tPercent:" + "\t%.3f\n", + totalShouldTransmit.GetMillisecondsF(), + totalShouldTransmit.GetMillisecondsF() * 100.0 / runningTime.GetMillisecondsF() + ); + + g_pFileSystem->FPrintf( fp, + "Total WriteDeltaProps ms:" + "\t%.3f" + "\tPercent:" + "\t%.3f\n", + totalDeltaProps.GetMillisecondsF(), + totalDeltaProps.GetMillisecondsF() * 100.0 / runningTime.GetMillisecondsF() + ); + + g_pFileSystem->Close( fp ); + + Msg( "DTI: Wrote delta distances into %s.\n", g_pServerDTIFilename ); + } + + + // Write the delta distances. + const char *pDeltaDistancesFilename = "dti_delta_distances.txt"; + fp = g_pFileSystem->Open( pDeltaDistancesFilename, "wt", "LOGDIR" ); + if( fp != FILESYSTEM_INVALID_HANDLE ) + { + // Write the column labels. + g_pFileSystem->FPrintf( fp, "ClassName" ); + for ( int i=0; i < NUM_DELTA_DISTANCE_BANDS; i++ ) + { + g_pFileSystem->FPrintf( fp, "\t<%d", (i+1) * DELTA_DISTANCE_BAND ); + } + g_pFileSystem->FPrintf( fp, "\n" ); + + // Now write the data. + FOR_EACH_LL( g_DTISendTables, j ) + { + CDTISendTable *pTable = g_DTISendTables[j]; + + if ( !pTable->HadAnyAction() ) + continue; + + g_pFileSystem->FPrintf( fp, "%s", pTable->m_NetTableName.String() ); + for ( int i=0; i < NUM_DELTA_DISTANCE_BANDS; i++ ) + { + g_pFileSystem->FPrintf( fp, "\t%d", pTable->m_DistanceDeltaCounts[i] ); + } + g_pFileSystem->FPrintf( fp, "\n" ); + } + + g_pFileSystem->Close( fp ); + + Msg( "DTI: Wrote instrumentation data into %s.\n", pDeltaDistancesFilename ); + } +} + + +CDTISendTable* ServerDTI_HookTable( SendTable *pTable ) +{ + if ( !g_bServerDTIEnabled ) + return NULL; + + CDTISendTable *pRet = new CDTISendTable; + memset( pRet, 0, sizeof( *pRet ) ); + + pRet->m_NetTableName.Set( pTable->m_pNetTableName ); + + g_DTISendTables.AddToTail( pRet ); + return pRet; +} + + +void ServerDTI_AddEntityEncodeEvent( SendTable *pSendTable, float distToPlayer ) +{ + CSendTablePrecalc *pPrecalc = pSendTable->m_pPrecalc; + if ( !pPrecalc || !pPrecalc->m_pDTITable ) + return; + + CDTISendTable *pTable = pPrecalc->m_pDTITable; + if ( !pTable ) + return; + + int iDist = (int)( distToPlayer / DELTA_DISTANCE_BAND ); + iDist = clamp( iDist, 0, NUM_DELTA_DISTANCE_BANDS - 1 ); + pTable->m_DistanceDeltaCounts[iDist]++; +} + +void _ServerDTI_HookTimer( const SendTable *pSendTable, ServerDTITimerType timerType, CCycleCount const &count ) +{ + CSendTablePrecalc *pPrecalc = pSendTable->m_pPrecalc; + if ( !pPrecalc || !pPrecalc->m_pDTITable ) + return; + + CDTISendTable *pTable = pPrecalc->m_pDTITable; + + if ( g_bFirstHookTimer ) + { + g_ServerDTITimer.Sample(); + g_bFirstHookTimer = false; + } + + // Add to the total cycles. + CCycleCount::Add( count, g_TotalServerDTICycles, g_TotalServerDTICycles ); + + if ( timerType == SERVERDTI_CALCDELTA ) + { + CCycleCount::Add( count, pTable->m_nCalcDeltaCycles, pTable->m_nCalcDeltaCycles ); + ++pTable->m_nCalcDeltaCalls; + } + else if ( timerType == SERVERDTI_ENCODE ) + { + CCycleCount::Add( count, pTable->m_nEncodeCycles, pTable->m_nEncodeCycles ); + ++pTable->m_nEncodeCalls; + } + else if ( timerType == SERVERDTI_SHOULDTRANSMIT ) + { + CCycleCount::Add( count, pTable->m_nShouldTransmitCycles, pTable->m_nShouldTransmitCycles ); + ++pTable->m_nShouldTransmitCalls; + } + else if ( timerType == SERVERDTI_WRITE_DELTA_PROPS ) + { + CCycleCount::Add( count, pTable->m_nWriteDeltaPropsCycles, pTable->m_nWriteDeltaPropsCycles ); + } +} + +void _ServerDTI_RegisterNetworkStateChange( SendTable *pSendTable, bool bStateChanged ) +{ + CSendTablePrecalc *pPrecalc = pSendTable->m_pPrecalc; + if ( !pPrecalc || !pPrecalc->m_pDTITable ) + return; + + CDTISendTable *pTable = pPrecalc->m_pDTITable; + + if ( bStateChanged ) + ++pTable->m_nChangeAutoDetects; + else + ++pTable->m_nNoChanges; +} + |