summaryrefslogtreecommitdiff
path: root/engine/dt_instrumentation_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engine/dt_instrumentation_server.cpp')
-rw-r--r--engine/dt_instrumentation_server.cpp357
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;
+}
+