diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /sp/src/game/server/serverbenchmark_base.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'sp/src/game/server/serverbenchmark_base.cpp')
| -rw-r--r-- | sp/src/game/server/serverbenchmark_base.cpp | 848 |
1 files changed, 424 insertions, 424 deletions
diff --git a/sp/src/game/server/serverbenchmark_base.cpp b/sp/src/game/server/serverbenchmark_base.cpp index 4fe3c6da..dbe7269a 100644 --- a/sp/src/game/server/serverbenchmark_base.cpp +++ b/sp/src/game/server/serverbenchmark_base.cpp @@ -1,424 +1,424 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================
-
-#include "cbase.h"
-#include "serverbenchmark_base.h"
-#include "props.h"
-#include "filesystem.h"
-#include "tier0/icommandline.h"
-
-
-// Server benchmark. Only works on specified maps.
-// Lasts for N ticks.
-// Enable sv_stressbots.
-// Create 20 players and move them around and have them shoot.
-// At the end, report the # seconds it took to complete the test.
-// Don't start measuring for the first N ticks to account for HD load.
-
-static ConVar sv_benchmark_numticks( "sv_benchmark_numticks", "3300", 0, "If > 0, then it only runs the benchmark for this # of ticks." );
-static ConVar sv_benchmark_autovprofrecord( "sv_benchmark_autovprofrecord", "0", 0, "If running a benchmark and this is set, it will record a vprof file over the duration of the benchmark with filename benchmark.vprof." );
-
-static float s_flBenchmarkStartWaitSeconds = 3; // Wait this many seconds after level load before starting the benchmark.
-
-static int s_nBenchmarkBotsToCreate = 22; // Create this many bots.
-static int s_nBenchmarkBotCreateInterval = 50; // Create a bot every N ticks.
-
-static int s_nBenchmarkPhysicsObjects = 100; // Create this many physics objects.
-
-
-static double Benchmark_ValidTime()
-{
- bool bOld = Plat_IsInBenchmarkMode();
- Plat_SetBenchmarkMode( false );
- double flRet = Plat_FloatTime();
- Plat_SetBenchmarkMode( bOld );
-
- return flRet;
-}
-
-
-// ---------------------------------------------------------------------------------------------- //
-// CServerBenchmark implementation.
-// ---------------------------------------------------------------------------------------------- //
-class CServerBenchmark : public IServerBenchmark
-{
-public:
- CServerBenchmark()
- {
- m_BenchmarkState = BENCHMARKSTATE_NOT_RUNNING;
-
- // The benchmark should always have the same seed and do exactly the same thing on the same ticks.
- m_RandomStream.SetSeed( 1111 );
- }
-
- virtual bool StartBenchmark()
- {
- bool bBenchmark = (CommandLine()->FindParm( "-sv_benchmark" ) != 0);
-
- return InternalStartBenchmark( bBenchmark, s_flBenchmarkStartWaitSeconds );
- }
-
- // nBenchmarkMode: 0 = no benchmark
- // 1 = benchmark
- // 2 = exit out afterwards and write sv_benchmark.txt
- bool InternalStartBenchmark( int nBenchmarkMode, float flCountdown )
- {
- bool bWasRunningBenchmark = (m_BenchmarkState != BENCHMARKSTATE_NOT_RUNNING);
-
- if ( nBenchmarkMode == 0 )
- {
- // Tear down the previous benchmark environment if necessary.
- if ( bWasRunningBenchmark )
- EndBenchmark();
- return false;
- }
-
- m_nBenchmarkMode = nBenchmarkMode;
-
- if ( !CServerBenchmarkHook::s_pBenchmarkHook )
- Error( "This game doesn't support server benchmarks (no CServerBenchmarkHook found)." );
-
- m_BenchmarkState = BENCHMARKSTATE_START_WAIT;
- m_flBenchmarkStartTime = Plat_FloatTime();
- m_flBenchmarkStartWaitTime = flCountdown;
-
- m_nBotsCreated = 0;
- m_nStartWaitCounter = -1;
-
- // Setup the benchmark environment.
- engine->SetDedicatedServerBenchmarkMode( true ); // Run 1 tick per frame and ignore all timing stuff.
-
- // Tell the game-specific hook that we're starting.
- CServerBenchmarkHook::s_pBenchmarkHook->StartBenchmark();
- CServerBenchmarkHook::s_pBenchmarkHook->GetPhysicsModelNames( m_PhysicsModelNames );
-
- return true;
- }
-
- virtual void UpdateBenchmark()
- {
- // No benchmark running?
- if ( m_BenchmarkState == BENCHMARKSTATE_NOT_RUNNING )
- return;
-
- // Wait a certain number of ticks to start the benchmark.
- if ( m_BenchmarkState == BENCHMARKSTATE_START_WAIT )
- {
- if ( (Plat_FloatTime() - m_flBenchmarkStartTime) < m_flBenchmarkStartWaitTime )
- {
- UpdateStartWaitCounter();
- return;
- }
- else
- {
- // Ok, now we're officially starting it.
- Msg( "Starting benchmark!\n" );
- m_flLastBenchmarkCounterUpdate = m_flBenchmarkStartTime = Plat_FloatTime();
- m_fl_ValidTime_BenchmarkStartTime = Benchmark_ValidTime();
- m_nBenchmarkStartTick = gpGlobals->tickcount;
- m_nLastPhysicsObjectTick = m_nLastPhysicsForceTick = 0;
- m_BenchmarkState = BENCHMARKSTATE_RUNNING;
-
- StartVProfRecord();
-
- RandomSeed( 0 );
- m_RandomStream.SetSeed( 0 );
- }
- }
-
- int nTicksRunSoFar = gpGlobals->tickcount - m_nBenchmarkStartTick;
- UpdateBenchmarkCounter();
-
- // Are we finished with the benchmark?
- if ( nTicksRunSoFar >= sv_benchmark_numticks.GetInt() )
- {
- EndVProfRecord();
- OutputResults();
- EndBenchmark();
- return;
- }
-
- // Ok, update whatever we're doing in the benchmark.
- UpdatePlayerCreation();
- UpdateVPhysicsObjects();
- CServerBenchmarkHook::s_pBenchmarkHook->UpdateBenchmark();
- }
-
- void StartVProfRecord()
- {
- if ( sv_benchmark_autovprofrecord.GetInt() )
- {
- engine->ServerCommand( "vprof_record_start benchmark\n" );
- engine->ServerExecute();
- }
- }
-
- void EndVProfRecord()
- {
- if ( sv_benchmark_autovprofrecord.GetInt() )
- {
- engine->ServerCommand( "vprof_record_stop\n" );
- engine->ServerExecute();
- }
- }
-
- virtual void EndBenchmark( void )
- {
- // Write out the results if we're running the build scripts.
- float flRunTime = Benchmark_ValidTime() - m_fl_ValidTime_BenchmarkStartTime;
- if ( m_nBenchmarkMode == 2 )
- {
- FileHandle_t fh = filesystem->Open( "sv_benchmark_results.txt", "wt", "DEFAULT_WRITE_PATH" );
-
- // If this file doesn't get written out, then the build script will generate an email that there's a problem somewhere.
- if ( fh )
- {
- filesystem->FPrintf( fh, "sv_benchmark := %.2f\n", flRunTime );
- }
- filesystem->Close( fh );
-
- // Quit out.
- engine->ServerCommand( "quit\n" );
- }
-
- m_BenchmarkState = BENCHMARKSTATE_NOT_RUNNING;
- engine->SetDedicatedServerBenchmarkMode( false );
- }
-
- virtual bool IsLocalBenchmarkPlayer( CBasePlayer *pPlayer )
- {
- if ( m_BenchmarkState != BENCHMARKSTATE_NOT_RUNNING )
- {
- if( !engine->IsDedicatedServer() && pPlayer->entindex() == 1 )
- return true;
- }
-
- return false;
- }
-
- void UpdateVPhysicsObjects()
- {
- int nPhysicsObjectInterval = sv_benchmark_numticks.GetInt() / s_nBenchmarkPhysicsObjects;
-
- int nNextSpawnTick = m_nLastPhysicsObjectTick + nPhysicsObjectInterval;
- if ( GetTickOffset() >= nNextSpawnTick )
- {
- m_nLastPhysicsObjectTick = nNextSpawnTick;
-
- if ( m_PhysicsObjects.Count() < s_nBenchmarkPhysicsObjects )
- {
- // Find a bot to spawn it from.
- CUtlVector<CBasePlayer*> curPlayers;
- for ( int i = 1; i <= gpGlobals->maxClients; i++ )
- {
- CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
- if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) )
- {
- curPlayers.AddToTail( pPlayer );
- }
- }
-
- if ( curPlayers.Count() > 0 && m_PhysicsModelNames.Count() > 0 )
- {
- int iModelName = this->RandomInt( 0, m_PhysicsModelNames.Count() - 1 );
- const char *pModelName = m_PhysicsModelNames[iModelName];
-
- int iPlayer = this->RandomInt( 0, curPlayers.Count() - 1 );
-
- Vector vSpawnPos = curPlayers[iPlayer]->EyePosition() + Vector( 0, 0, 50 );
-
- // We'll try 15 locations around the player to spawn this thing.
- for ( int i=0; i < 15; i++ )
- {
- Vector vOffset( this->RandomFloat( -2000, 2000 ), this->RandomFloat( -2000, 2000 ), 0 );
- CPhysicsProp *pProp = CreatePhysicsProp( pModelName, vSpawnPos, vSpawnPos+vOffset, curPlayers[iPlayer], false, "prop_physics_multiplayer" );
- if ( pProp )
- {
- m_PhysicsObjects.AddToTail( pProp );
- pProp->SetAbsVelocity( Vector( this->RandomFloat(-500,500), this->RandomFloat(-500,500), this->RandomFloat(-500,500) ) );
- break;
- }
- }
- }
- }
- }
-
- // Give them all a boost periodically.
- int nPhysicsForceInterval = sv_benchmark_numticks.GetInt() / 20;
-
- int nNextForceTick = m_nLastPhysicsForceTick + nPhysicsForceInterval;
- if ( GetTickOffset() >= nNextForceTick )
- {
- m_nLastPhysicsForceTick = nNextForceTick;
-
- for ( int i=0; i < m_PhysicsObjects.Count(); i++ )
- {
- CBaseEntity *pEnt = m_PhysicsObjects[i];
- if ( pEnt )
- {
- IPhysicsObject *pPhysicsObject = pEnt->VPhysicsGetObject();
- if ( pPhysicsObject )
- {
- float flAngImpulse = 300000;
- float flForce = 500000;
- AngularImpulse vAngularImpulse( this->RandomFloat(-flAngImpulse,flAngImpulse), this->RandomFloat(-flAngImpulse,flAngImpulse), this->RandomFloat(flAngImpulse,flAngImpulse) );
- pPhysicsObject->ApplyForceCenter( Vector( this->RandomFloat(-flForce,flForce), this->RandomFloat(-flForce,flForce), this->RandomFloat(0,flForce) ) );
- }
- }
- }
- }
- }
-
- void UpdateStartWaitCounter()
- {
- int nSecondsLeft = (int)ceil( m_flBenchmarkStartWaitTime - (Plat_FloatTime() - m_flBenchmarkStartTime) );
- if ( m_nStartWaitCounter != nSecondsLeft )
- {
- Msg( "Starting benchmark in %d seconds...\n", nSecondsLeft );
- m_nStartWaitCounter = nSecondsLeft;
- }
- }
-
- void UpdateBenchmarkCounter()
- {
- float flCurTime = Plat_FloatTime();
- if ( (flCurTime - m_flLastBenchmarkCounterUpdate) > 3.0f )
- {
- m_flLastBenchmarkCounterUpdate = flCurTime;
- Msg( "Benchmark: %d%% complete.\n", ((gpGlobals->tickcount - m_nBenchmarkStartTick) * 100) / sv_benchmark_numticks.GetInt() );
- }
- }
-
- virtual bool IsBenchmarkRunning()
- {
- return (m_BenchmarkState == BENCHMARKSTATE_RUNNING);
- }
-
- virtual int GetTickOffset()
- {
- if ( m_BenchmarkState == BENCHMARKSTATE_RUNNING )
- {
- Assert( gpGlobals->tickcount >= m_nBenchmarkStartTick );
- return gpGlobals->tickcount - m_nBenchmarkStartTick;
- }
- else
- {
- return gpGlobals->tickcount;
- }
- }
-
-
- void UpdatePlayerCreation()
- {
- if ( m_nBotsCreated >= s_nBenchmarkBotsToCreate )
- return;
-
- // Spawn the player.
- int nTicksRunSoFar = gpGlobals->tickcount - m_nBenchmarkStartTick;
-
- if ( (nTicksRunSoFar % s_nBenchmarkBotCreateInterval) == 0 )
- {
- CServerBenchmarkHook::s_pBenchmarkHook->CreateBot();
- ++m_nBotsCreated;
- }
- }
-
- void OutputResults()
- {
- float flRunTime = Benchmark_ValidTime() - m_fl_ValidTime_BenchmarkStartTime;
-
- Warning( "------------------ SERVER BENCHMARK RESULTS ------------------\n" );
- Warning( "Total time : %.2f seconds\n", flRunTime );
- Warning( "Num ticks simulated : %d\n", sv_benchmark_numticks.GetInt() );
- Warning( "Ticks per second : %.2f\n", sv_benchmark_numticks.GetInt() / flRunTime );
- Warning( "Benchmark CRC : %d\n", CalculateBenchmarkCRC() );
- Warning( "--------------------------------------------------------------\n" );
- }
-
- int CalculateBenchmarkCRC()
- {
- int crc = 0;
-
- for ( int i = 1; i <= gpGlobals->maxClients; i++ )
- {
- CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
- if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) )
- {
- crc += pPlayer->GetTeamNumber();
- crc += (int)pPlayer->GetAbsOrigin().x;
- crc += (int)pPlayer->GetAbsOrigin().y;
- }
- }
-
- return crc;
- }
-
- virtual int RandomInt( int nMin, int nMax )
- {
- return m_RandomStream.RandomInt( nMin, nMax );
- }
-
- virtual float RandomFloat( float nMin, float nMax )
- {
- return m_RandomStream.RandomInt( nMin, nMax );
- }
-
-
-private:
-
- enum EBenchmarkState
- {
- BENCHMARKSTATE_NOT_RUNNING,
- BENCHMARKSTATE_START_WAIT,
- BENCHMARKSTATE_RUNNING
- };
- EBenchmarkState m_BenchmarkState;
-
- float m_fl_ValidTime_BenchmarkStartTime;
-
- float m_flBenchmarkStartTime;
- float m_flLastBenchmarkCounterUpdate;
- float m_flBenchmarkStartWaitTime;
-
- int m_nBenchmarkStartTick;
- int m_nStartWaitCounter;
- int m_nLastPhysicsObjectTick;
- int m_nLastPhysicsForceTick;
-
- int m_nBotsCreated;
- CUtlVector< EHANDLE > m_PhysicsObjects;
-
- CUtlVector<char*> m_PhysicsModelNames;
- int m_nBenchmarkMode;
-
- CUniformRandomStream m_RandomStream;
-};
-
-static CServerBenchmark g_ServerBenchmark;
-IServerBenchmark *g_pServerBenchmark = &g_ServerBenchmark;
-
-CON_COMMAND( sv_benchmark_force_start, "Force start the benchmark. This is only for debugging. It's better to set sv_benchmark to 1 and restart the level." )
-{
- if ( !UTIL_IsCommandIssuedByServerAdmin() )
- return;
-
- g_ServerBenchmark.InternalStartBenchmark( 1, 1 );
-}
-
-
-// ---------------------------------------------------------------------------------------------- //
-// CServerBenchmarkHook implementation.
-// ---------------------------------------------------------------------------------------------- //
-
-CServerBenchmarkHook *CServerBenchmarkHook::s_pBenchmarkHook = NULL;
-
-CServerBenchmarkHook::CServerBenchmarkHook()
-{
- if ( s_pBenchmarkHook )
- Error( "There can only be one CServerBenchmarkHook" );
-
- s_pBenchmarkHook = this;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "cbase.h" +#include "serverbenchmark_base.h" +#include "props.h" +#include "filesystem.h" +#include "tier0/icommandline.h" + + +// Server benchmark. Only works on specified maps. +// Lasts for N ticks. +// Enable sv_stressbots. +// Create 20 players and move them around and have them shoot. +// At the end, report the # seconds it took to complete the test. +// Don't start measuring for the first N ticks to account for HD load. + +static ConVar sv_benchmark_numticks( "sv_benchmark_numticks", "3300", 0, "If > 0, then it only runs the benchmark for this # of ticks." ); +static ConVar sv_benchmark_autovprofrecord( "sv_benchmark_autovprofrecord", "0", 0, "If running a benchmark and this is set, it will record a vprof file over the duration of the benchmark with filename benchmark.vprof." ); + +static float s_flBenchmarkStartWaitSeconds = 3; // Wait this many seconds after level load before starting the benchmark. + +static int s_nBenchmarkBotsToCreate = 22; // Create this many bots. +static int s_nBenchmarkBotCreateInterval = 50; // Create a bot every N ticks. + +static int s_nBenchmarkPhysicsObjects = 100; // Create this many physics objects. + + +static double Benchmark_ValidTime() +{ + bool bOld = Plat_IsInBenchmarkMode(); + Plat_SetBenchmarkMode( false ); + double flRet = Plat_FloatTime(); + Plat_SetBenchmarkMode( bOld ); + + return flRet; +} + + +// ---------------------------------------------------------------------------------------------- // +// CServerBenchmark implementation. +// ---------------------------------------------------------------------------------------------- // +class CServerBenchmark : public IServerBenchmark +{ +public: + CServerBenchmark() + { + m_BenchmarkState = BENCHMARKSTATE_NOT_RUNNING; + + // The benchmark should always have the same seed and do exactly the same thing on the same ticks. + m_RandomStream.SetSeed( 1111 ); + } + + virtual bool StartBenchmark() + { + bool bBenchmark = (CommandLine()->FindParm( "-sv_benchmark" ) != 0); + + return InternalStartBenchmark( bBenchmark, s_flBenchmarkStartWaitSeconds ); + } + + // nBenchmarkMode: 0 = no benchmark + // 1 = benchmark + // 2 = exit out afterwards and write sv_benchmark.txt + bool InternalStartBenchmark( int nBenchmarkMode, float flCountdown ) + { + bool bWasRunningBenchmark = (m_BenchmarkState != BENCHMARKSTATE_NOT_RUNNING); + + if ( nBenchmarkMode == 0 ) + { + // Tear down the previous benchmark environment if necessary. + if ( bWasRunningBenchmark ) + EndBenchmark(); + return false; + } + + m_nBenchmarkMode = nBenchmarkMode; + + if ( !CServerBenchmarkHook::s_pBenchmarkHook ) + Error( "This game doesn't support server benchmarks (no CServerBenchmarkHook found)." ); + + m_BenchmarkState = BENCHMARKSTATE_START_WAIT; + m_flBenchmarkStartTime = Plat_FloatTime(); + m_flBenchmarkStartWaitTime = flCountdown; + + m_nBotsCreated = 0; + m_nStartWaitCounter = -1; + + // Setup the benchmark environment. + engine->SetDedicatedServerBenchmarkMode( true ); // Run 1 tick per frame and ignore all timing stuff. + + // Tell the game-specific hook that we're starting. + CServerBenchmarkHook::s_pBenchmarkHook->StartBenchmark(); + CServerBenchmarkHook::s_pBenchmarkHook->GetPhysicsModelNames( m_PhysicsModelNames ); + + return true; + } + + virtual void UpdateBenchmark() + { + // No benchmark running? + if ( m_BenchmarkState == BENCHMARKSTATE_NOT_RUNNING ) + return; + + // Wait a certain number of ticks to start the benchmark. + if ( m_BenchmarkState == BENCHMARKSTATE_START_WAIT ) + { + if ( (Plat_FloatTime() - m_flBenchmarkStartTime) < m_flBenchmarkStartWaitTime ) + { + UpdateStartWaitCounter(); + return; + } + else + { + // Ok, now we're officially starting it. + Msg( "Starting benchmark!\n" ); + m_flLastBenchmarkCounterUpdate = m_flBenchmarkStartTime = Plat_FloatTime(); + m_fl_ValidTime_BenchmarkStartTime = Benchmark_ValidTime(); + m_nBenchmarkStartTick = gpGlobals->tickcount; + m_nLastPhysicsObjectTick = m_nLastPhysicsForceTick = 0; + m_BenchmarkState = BENCHMARKSTATE_RUNNING; + + StartVProfRecord(); + + RandomSeed( 0 ); + m_RandomStream.SetSeed( 0 ); + } + } + + int nTicksRunSoFar = gpGlobals->tickcount - m_nBenchmarkStartTick; + UpdateBenchmarkCounter(); + + // Are we finished with the benchmark? + if ( nTicksRunSoFar >= sv_benchmark_numticks.GetInt() ) + { + EndVProfRecord(); + OutputResults(); + EndBenchmark(); + return; + } + + // Ok, update whatever we're doing in the benchmark. + UpdatePlayerCreation(); + UpdateVPhysicsObjects(); + CServerBenchmarkHook::s_pBenchmarkHook->UpdateBenchmark(); + } + + void StartVProfRecord() + { + if ( sv_benchmark_autovprofrecord.GetInt() ) + { + engine->ServerCommand( "vprof_record_start benchmark\n" ); + engine->ServerExecute(); + } + } + + void EndVProfRecord() + { + if ( sv_benchmark_autovprofrecord.GetInt() ) + { + engine->ServerCommand( "vprof_record_stop\n" ); + engine->ServerExecute(); + } + } + + virtual void EndBenchmark( void ) + { + // Write out the results if we're running the build scripts. + float flRunTime = Benchmark_ValidTime() - m_fl_ValidTime_BenchmarkStartTime; + if ( m_nBenchmarkMode == 2 ) + { + FileHandle_t fh = filesystem->Open( "sv_benchmark_results.txt", "wt", "DEFAULT_WRITE_PATH" ); + + // If this file doesn't get written out, then the build script will generate an email that there's a problem somewhere. + if ( fh ) + { + filesystem->FPrintf( fh, "sv_benchmark := %.2f\n", flRunTime ); + } + filesystem->Close( fh ); + + // Quit out. + engine->ServerCommand( "quit\n" ); + } + + m_BenchmarkState = BENCHMARKSTATE_NOT_RUNNING; + engine->SetDedicatedServerBenchmarkMode( false ); + } + + virtual bool IsLocalBenchmarkPlayer( CBasePlayer *pPlayer ) + { + if ( m_BenchmarkState != BENCHMARKSTATE_NOT_RUNNING ) + { + if( !engine->IsDedicatedServer() && pPlayer->entindex() == 1 ) + return true; + } + + return false; + } + + void UpdateVPhysicsObjects() + { + int nPhysicsObjectInterval = sv_benchmark_numticks.GetInt() / s_nBenchmarkPhysicsObjects; + + int nNextSpawnTick = m_nLastPhysicsObjectTick + nPhysicsObjectInterval; + if ( GetTickOffset() >= nNextSpawnTick ) + { + m_nLastPhysicsObjectTick = nNextSpawnTick; + + if ( m_PhysicsObjects.Count() < s_nBenchmarkPhysicsObjects ) + { + // Find a bot to spawn it from. + CUtlVector<CBasePlayer*> curPlayers; + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) ) + { + curPlayers.AddToTail( pPlayer ); + } + } + + if ( curPlayers.Count() > 0 && m_PhysicsModelNames.Count() > 0 ) + { + int iModelName = this->RandomInt( 0, m_PhysicsModelNames.Count() - 1 ); + const char *pModelName = m_PhysicsModelNames[iModelName]; + + int iPlayer = this->RandomInt( 0, curPlayers.Count() - 1 ); + + Vector vSpawnPos = curPlayers[iPlayer]->EyePosition() + Vector( 0, 0, 50 ); + + // We'll try 15 locations around the player to spawn this thing. + for ( int i=0; i < 15; i++ ) + { + Vector vOffset( this->RandomFloat( -2000, 2000 ), this->RandomFloat( -2000, 2000 ), 0 ); + CPhysicsProp *pProp = CreatePhysicsProp( pModelName, vSpawnPos, vSpawnPos+vOffset, curPlayers[iPlayer], false, "prop_physics_multiplayer" ); + if ( pProp ) + { + m_PhysicsObjects.AddToTail( pProp ); + pProp->SetAbsVelocity( Vector( this->RandomFloat(-500,500), this->RandomFloat(-500,500), this->RandomFloat(-500,500) ) ); + break; + } + } + } + } + } + + // Give them all a boost periodically. + int nPhysicsForceInterval = sv_benchmark_numticks.GetInt() / 20; + + int nNextForceTick = m_nLastPhysicsForceTick + nPhysicsForceInterval; + if ( GetTickOffset() >= nNextForceTick ) + { + m_nLastPhysicsForceTick = nNextForceTick; + + for ( int i=0; i < m_PhysicsObjects.Count(); i++ ) + { + CBaseEntity *pEnt = m_PhysicsObjects[i]; + if ( pEnt ) + { + IPhysicsObject *pPhysicsObject = pEnt->VPhysicsGetObject(); + if ( pPhysicsObject ) + { + float flAngImpulse = 300000; + float flForce = 500000; + AngularImpulse vAngularImpulse( this->RandomFloat(-flAngImpulse,flAngImpulse), this->RandomFloat(-flAngImpulse,flAngImpulse), this->RandomFloat(flAngImpulse,flAngImpulse) ); + pPhysicsObject->ApplyForceCenter( Vector( this->RandomFloat(-flForce,flForce), this->RandomFloat(-flForce,flForce), this->RandomFloat(0,flForce) ) ); + } + } + } + } + } + + void UpdateStartWaitCounter() + { + int nSecondsLeft = (int)ceil( m_flBenchmarkStartWaitTime - (Plat_FloatTime() - m_flBenchmarkStartTime) ); + if ( m_nStartWaitCounter != nSecondsLeft ) + { + Msg( "Starting benchmark in %d seconds...\n", nSecondsLeft ); + m_nStartWaitCounter = nSecondsLeft; + } + } + + void UpdateBenchmarkCounter() + { + float flCurTime = Plat_FloatTime(); + if ( (flCurTime - m_flLastBenchmarkCounterUpdate) > 3.0f ) + { + m_flLastBenchmarkCounterUpdate = flCurTime; + Msg( "Benchmark: %d%% complete.\n", ((gpGlobals->tickcount - m_nBenchmarkStartTick) * 100) / sv_benchmark_numticks.GetInt() ); + } + } + + virtual bool IsBenchmarkRunning() + { + return (m_BenchmarkState == BENCHMARKSTATE_RUNNING); + } + + virtual int GetTickOffset() + { + if ( m_BenchmarkState == BENCHMARKSTATE_RUNNING ) + { + Assert( gpGlobals->tickcount >= m_nBenchmarkStartTick ); + return gpGlobals->tickcount - m_nBenchmarkStartTick; + } + else + { + return gpGlobals->tickcount; + } + } + + + void UpdatePlayerCreation() + { + if ( m_nBotsCreated >= s_nBenchmarkBotsToCreate ) + return; + + // Spawn the player. + int nTicksRunSoFar = gpGlobals->tickcount - m_nBenchmarkStartTick; + + if ( (nTicksRunSoFar % s_nBenchmarkBotCreateInterval) == 0 ) + { + CServerBenchmarkHook::s_pBenchmarkHook->CreateBot(); + ++m_nBotsCreated; + } + } + + void OutputResults() + { + float flRunTime = Benchmark_ValidTime() - m_fl_ValidTime_BenchmarkStartTime; + + Warning( "------------------ SERVER BENCHMARK RESULTS ------------------\n" ); + Warning( "Total time : %.2f seconds\n", flRunTime ); + Warning( "Num ticks simulated : %d\n", sv_benchmark_numticks.GetInt() ); + Warning( "Ticks per second : %.2f\n", sv_benchmark_numticks.GetInt() / flRunTime ); + Warning( "Benchmark CRC : %d\n", CalculateBenchmarkCRC() ); + Warning( "--------------------------------------------------------------\n" ); + } + + int CalculateBenchmarkCRC() + { + int crc = 0; + + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) ) + { + crc += pPlayer->GetTeamNumber(); + crc += (int)pPlayer->GetAbsOrigin().x; + crc += (int)pPlayer->GetAbsOrigin().y; + } + } + + return crc; + } + + virtual int RandomInt( int nMin, int nMax ) + { + return m_RandomStream.RandomInt( nMin, nMax ); + } + + virtual float RandomFloat( float nMin, float nMax ) + { + return m_RandomStream.RandomInt( nMin, nMax ); + } + + +private: + + enum EBenchmarkState + { + BENCHMARKSTATE_NOT_RUNNING, + BENCHMARKSTATE_START_WAIT, + BENCHMARKSTATE_RUNNING + }; + EBenchmarkState m_BenchmarkState; + + float m_fl_ValidTime_BenchmarkStartTime; + + float m_flBenchmarkStartTime; + float m_flLastBenchmarkCounterUpdate; + float m_flBenchmarkStartWaitTime; + + int m_nBenchmarkStartTick; + int m_nStartWaitCounter; + int m_nLastPhysicsObjectTick; + int m_nLastPhysicsForceTick; + + int m_nBotsCreated; + CUtlVector< EHANDLE > m_PhysicsObjects; + + CUtlVector<char*> m_PhysicsModelNames; + int m_nBenchmarkMode; + + CUniformRandomStream m_RandomStream; +}; + +static CServerBenchmark g_ServerBenchmark; +IServerBenchmark *g_pServerBenchmark = &g_ServerBenchmark; + +CON_COMMAND( sv_benchmark_force_start, "Force start the benchmark. This is only for debugging. It's better to set sv_benchmark to 1 and restart the level." ) +{ + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; + + g_ServerBenchmark.InternalStartBenchmark( 1, 1 ); +} + + +// ---------------------------------------------------------------------------------------------- // +// CServerBenchmarkHook implementation. +// ---------------------------------------------------------------------------------------------- // + +CServerBenchmarkHook *CServerBenchmarkHook::s_pBenchmarkHook = NULL; + +CServerBenchmarkHook::CServerBenchmarkHook() +{ + if ( s_pBenchmarkHook ) + Error( "There can only be one CServerBenchmarkHook" ); + + s_pBenchmarkHook = this; +} |