Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SendAllActions work is slow #26

Open
kirill-782 opened this issue Jan 12, 2019 · 0 comments
Open

SendAllActions work is slow #26

kirill-782 opened this issue Jan 12, 2019 · 0 comments

Comments

@kirill-782
Copy link
Contributor

Have this code

void CBaseGame :: SendAllActions( )
{
	bool UsingGProxy = false;

	uint32_t start = GetTicks( );

	for( vector<CGamePlayer *> :: iterator i = m_Players.begin( ); i != m_Players.end( ); ++i )
	{
		if( (*i)->GetGProxy( ) )
			UsingGProxy = true;
	}

	//TrackTimeCode( "SAAUGP", GetTicks( ) - start );
	//start = GetTicks( );

	m_GameTicks += m_Latency;

	if( UsingGProxy )
	{
		// we must send empty actions to non-GProxy++ players
		// GProxy++ will insert these itself so we don't need to send them to GProxy++ players
		// empty actions are used to extend the time a player can use when reconnecting

		for( vector<CGamePlayer *> :: iterator i = m_Players.begin( ); i != m_Players.end( ); ++i )
		{
			if( !(*i)->GetGProxy( ) )
			{
				for( unsigned char j = 0; j < m_GProxyEmptyActions; ++j )
					Send( *i, m_Protocol->SEND_W3GS_INCOMING_ACTION( queue<CIncomingAction *>( ), 0 ) );
			}
		}

		if( m_Replay )
		{
			for( unsigned char i = 0; i < m_GProxyEmptyActions; ++i )
				m_Replay->AddTimeSlot( 0, queue<CIncomingAction *>( ) );
		}
	}

	//TrackTimeCode( "SAAIFGP", GetTicks( ) - start );
	//start = GetTicks( );

	// Warcraft III doesn't seem to respond to empty actions

	/* if( UsingGProxy )
		m_SyncCounter += m_GProxyEmptyActions; */

	++m_SyncCounter;


	//TrackTimeCode( "SAADLC", GetTicks( ) - start );
	//start = GetTicks( );

	// we aren't allowed to send more than 1460 bytes in a single packet but it's possible we might have more than that many bytes waiting in the queue

	if( !m_Actions.empty( ) )
	{
		// we use a "sub actions queue" which we keep adding actions to until we reach the size limit
		// start by adding one action to the sub actions queue

		uint32_t start2 = GetTicks( );

		queue<CIncomingAction *> SubActions;
		CIncomingAction *Action = m_Actions.front( );
		m_Actions.pop( );
		SubActions.push( Action );
		uint32_t SubActionsLength = Action->GetLength( );

		//TrackTimeCode( "SAADLC1", GetTicks( ) - start2 );
		//start2 = GetTicks( );

		while( !m_Actions.empty( ) )
		{
			Action = m_Actions.front( );
			m_Actions.pop( );

			// check if adding the next action to the sub actions queue would put us over the limit (1452 because the INCOMING_ACTION and INCOMING_ACTION2 packets use an extra 8 bytes)

			if( SubActionsLength + Action->GetLength( ) > 1452 )
			{
				uint32_t start3 = GetTicks( );

				// we'd be over the limit if we added the next action to the sub actions queue
				// so send everything already in the queue and then clear it out
				// the W3GS_INCOMING_ACTION2 packet handles the overflow but it must be sent *before* the corresponding W3GS_INCOMING_ACTION packet

				SendAll( m_Protocol->SEND_W3GS_INCOMING_ACTION2( SubActions ) );

				if( m_Replay )
					m_Replay->AddTimeSlot2( SubActions );

				while( !SubActions.empty( ) )
				{
					delete SubActions.front( );
					SubActions.pop( );
				}

				SubActionsLength = 0;

				//TrackTimeCode( "SAADLC13", GetTicks( ) - start3 );
			}

			SubActions.push( Action );
			SubActionsLength += Action->GetLength( );
			
		}

		//TrackTimeCode( "SAADLC2", GetTicks( ) - start2 );

		SendAll( m_Protocol->SEND_W3GS_INCOMING_ACTION( SubActions, m_Latency ) );

		if( m_Replay )
			m_Replay->AddTimeSlot( m_Latency, SubActions );

		while( !SubActions.empty( ) )
		{
			delete SubActions.front( );
			SubActions.pop( );
		}
	}
	else
	{
		SendAll( m_Protocol->SEND_W3GS_INCOMING_ACTION( m_Actions, m_Latency ) );

		if( m_Replay )
			m_Replay->AddTimeSlot( m_Latency, m_Actions );
	}

	//TrackTimeCode( "SAAWH", GetTicks( ) - start );
	//start = GetTicks( );

	uint32_t ActualSendInterval = GetTicks( ) - m_LastActionSentTicks;
	uint32_t ExpectedSendInterval = m_Latency - m_LastActionLateBy;
	m_LastActionLateBy = ActualSendInterval - ExpectedSendInterval;

	if( m_LastActionLateBy > m_Latency )
	{
		// something is going terribly wrong - GHost++ is probably starved of resources
		// print a message because even though this will take more resources it should provide some information to the administrator for future reference
		// other solutions - dynamically modify the latency, request higher priority, terminate other games, ???
		//To causes a performance problem, when the console has to say this 1000 times. Should improve ghost hosting on servers
		CONSOLE_Print( "[GAME: " + m_GameName + "] warning - the latency is " + UTIL_ToString( m_Latency ) + "ms but the last update was late by " + UTIL_ToString( m_LastActionLateBy ) + "ms" );
		m_LastActionLateBy = m_Latency;

	}

	m_LastActionSentTicks = GetTicks( );

	//TrackTimeCode( "SAACALC", GetTicks( ) - start );
}

Using the code execution time measurements, I found out that this method is slow. And it is slow to work those code which, in principle, are not long to work (see SAACALC). An example of one measurement from one game.

End report: twilka
Loaded
ACMO: 12 times, time exec: 327
SAACALC: 5 times, time exec: 179
SAADLC: 3 times, time exec: 11
SAADLC1: 6 times, time exec: 194
SAADLC13: 1 times, time exec: 0
SAADLC2: 4 times, time exec: 56
SAAIFGP: 4 times, time exec: 18
SAAUGP: 3 times, time exec: 50
SAAWH: 10 times, time exec: 327
SCKICK: 3 times, time exec: 8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant