From 16d25210e47963ab1ef8901768ae8f9f21c2d3cf Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Wed, 13 Mar 2013 21:32:48 +0000 Subject: [PATCH] - make client use less CPU for network games --- .../menu/menu_state_connected_game.cpp | 1 + .../glest_game/network/client_interface.cpp | 100 +++++++++++++++--- source/glest_game/network/client_interface.h | 2 +- .../glest_game/network/network_interface.cpp | 5 +- source/glest_game/network/network_interface.h | 2 +- .../sources/platform/posix/socket.cpp | 7 +- 6 files changed, 92 insertions(+), 25 deletions(-) diff --git a/source/glest_game/menu/menu_state_connected_game.cpp b/source/glest_game/menu/menu_state_connected_game.cpp index 88118ac68..0dee6125a 100644 --- a/source/glest_game/menu/menu_state_connected_game.cpp +++ b/source/glest_game/menu/menu_state_connected_game.cpp @@ -3882,6 +3882,7 @@ void MenuStateConnectedGame::FTPClient_CallbackEvent(string itemName, } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] szMsg [%s] lastProgress.first = %d, fileProgress = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,szMsg,lastProgress.first,fileProgress); clientInterface->sendTextMessage(szMsg,-1, lang.isLanguageLocal(languageList[i]),languageList[i]); + sleep(1); } } } diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index 33ab7366d..01bf2ea06 100644 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -37,6 +37,8 @@ using namespace Shared::Util; namespace Glest{ namespace Game{ +const bool debugClientInterfacePerf = false; + // ===================================================== // class ClientInterfaceThread // ===================================================== @@ -85,6 +87,11 @@ void ClientInterfaceThread::execute() { bool minorDebugPerformance = false; Chrono chrono; + // Set socket to blocking + if(clientInterface != NULL && clientInterface->getSocket(true) != NULL) { + clientInterface->getSocket(true)->setBlock(true); + } + //unsigned int idx = 0; for(;this->clientInterface != NULL;) { if(getQuitStatus() == true) { @@ -108,20 +115,29 @@ void ClientInterfaceThread::execute() { //if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); - //printf("START === Client thread ended\n"); + if(debugClientInterfacePerf == true) printf("START === Client thread\n"); - Chrono chrono(true); + uint64 loopCount = 0; + Chrono chrono; + if(debugClientInterfacePerf == true) { + chrono.start(); + } while(this->getQuitStatus() == false && clientInterface != NULL) { clientInterface->updateNetworkFrame(); - if(chrono.getMillis() >= 200) { - sleep(5); - chrono.start(); - } + if(debugClientInterfacePerf == true) { + loopCount++; + if(chrono.getMillis() >= 1000) { + printf("Client thread loopCount = %llu\n",(long long unsigned int)loopCount); + loopCount = 0; + //sleep(0); + chrono.start(); + } + } } - //printf("END === Client thread ended\n"); + if(debugClientInterfacePerf == true)printf("END === Client thread\n"); //if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis()); @@ -866,9 +882,16 @@ void ClientInterface::updateFrame(int *checkFrame) { if(isConnected() == true && this->quitThread == false) { //printf("#2 ClientInterface::updateFrame\n"); + uint64 loopCount = 0; + Chrono chronoPerf; + if(debugClientInterfacePerf == true) { + chronoPerf.start(); + } + Chrono chrono; chrono.start(); + int waitMilliseconds = (checkFrame == NULL ? 1 : 0); int simulateLag = Config::getInstance().getInt("SimulateClientLag","0"); bool done= false; while(done == false && this->quitThread == false) { @@ -876,7 +899,7 @@ void ClientInterface::updateFrame(int *checkFrame) { //printf("BEFORE Client get networkMessageType\n"); //wait for the next message - NetworkMessageType networkMessageType = waitForMessage(); + NetworkMessageType networkMessageType = waitForMessage(waitMilliseconds); //printf("AFTER Client got networkMessageType = %d\n",networkMessageType); @@ -1121,8 +1144,19 @@ void ClientInterface::updateFrame(int *checkFrame) { done = true; } // Sleep ever second we wait to let other threads work - else if(chrono.getMillis() % 25 == 0) { - sleep(1); +// else if(chrono.getMillis() % 25 == 0) { +// sleep(1); +// } + + if(debugClientInterfacePerf == true) { + loopCount++; + if(chronoPerf.getMillis() >= 1000) { + printf("Client updateFrame loopCount = %llu\n",(long long unsigned int)loopCount); + + loopCount = 0; + //sleep(0); + chronoPerf.start(); + } } } @@ -1132,7 +1166,7 @@ void ClientInterface::updateFrame(int *checkFrame) { } else if(checkFrame == NULL) { //sleep(15); - sleep(0); + //sleep(0); } } //printf("#3 ClientInterface::updateFrame\n"); @@ -1165,14 +1199,24 @@ bool ClientInterface::getNetworkCommand(int frameCount, int currentCachedPending bool result = false; bool waitForData = false; + uint64 copyCachedLastPendingFrameCount = 0; + uint64 waitCount = 0; + if(quit == false && this->quitThread == false) { //MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE); //safeMutex.ReleaseLock(true); + MutexSafeWrapper safeMutex(NULL,CODE_AT_LINE); for(;quit == false && this->quitThread == false;) { - MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE); + //MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE); //safeMutex.Lock(); - uint64 copyCachedLastPendingFrameCount = cachedLastPendingFrameCount; + if(safeMutex.isValidMutex() == false) { + safeMutex.setMutex(networkCommandListThreadAccessor,CODE_AT_LINE); + } + else { + safeMutex.Lock(); + } + copyCachedLastPendingFrameCount = cachedLastPendingFrameCount; if(cachedPendingCommands.find(frameCount) != cachedPendingCommands.end()) { Commands &frameCmdList = cachedPendingCommands[frameCount]; if(frameCmdList.size() > 0) { @@ -1203,13 +1247,18 @@ bool ClientInterface::getNetworkCommand(int frameCount, int currentCachedPending if(waitForData == false) { waitForData = true; - sleep(1); + sleep(0); } + waitCount++; + //printf("Client waiting for packet for frame: %d, currentCachedPendingCommandsIndex = %d, cachedPendingCommandsIndex = %lld\n",frameCount,currentCachedPendingCommandsIndex,(long long int)cachedPendingCommandsIndex); } } } + if(waitForData == true) { + printf("Client waiting for packet FINISHED for frame: %d, copyCachedLastPendingFrameCount = %lld waitCount = %llu\n",frameCount,(long long int)copyCachedLastPendingFrameCount,(long long unsigned int)waitCount); + } return result; } @@ -1659,7 +1708,7 @@ string ClientInterface::getNetworkStatus() { return szBuf; } -NetworkMessageType ClientInterface::waitForMessage() +NetworkMessageType ClientInterface::waitForMessage(int waitMilliseconds) { // Debug! /* @@ -1670,13 +1719,19 @@ NetworkMessageType ClientInterface::waitForMessage() return; */ + uint64 loopCount = 0; + Chrono chronoPerf; + if(debugClientInterfacePerf == true) { + chronoPerf.start(); + } + Chrono chrono; chrono.start(); NetworkMessageType msg = nmtInvalid; //uint64 waitLoopCount = 0; while(msg == nmtInvalid && this->quitThread == false) { - msg = getNextMessageType(); + msg = getNextMessageType(waitMilliseconds); if(msg == nmtInvalid) { if(chrono.getMillis() % 250 == 0 && isConnected() == false) { if(quit == false) { @@ -1715,12 +1770,23 @@ NetworkMessageType ClientInterface::waitForMessage() } // Sleep ever second we wait to let other threads work else if(chrono.getMillis() % 25 == 0) { - sleep(1); + sleep(5); } //sleep(waitSleepTime); } //waitLoopCount++; + + if(debugClientInterfacePerf == true) { + loopCount++; + if(chronoPerf.getMillis() >= 100) { + printf("Client waitForMessage loopCount = %llu\n",(long long unsigned int)loopCount); + + loopCount = 0; + //sleep(0); + chronoPerf.start(); + } + } } //if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] waiting took %lld msecs, waitLoopCount = %ull, msg = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis(),waitLoopCount,msg); diff --git a/source/glest_game/network/client_interface.h b/source/glest_game/network/client_interface.h index a346ee32b..aa3edf9e0 100644 --- a/source/glest_game/network/client_interface.h +++ b/source/glest_game/network/client_interface.h @@ -186,7 +186,7 @@ public: protected: Mutex * getServerSynchAccessor() { return NULL; } - NetworkMessageType waitForMessage(); + NetworkMessageType waitForMessage(int waitMilliseconds=0); bool shouldDiscardNetworkMessage(NetworkMessageType networkMessageType); void updateFrame(int *checkFrame); diff --git a/source/glest_game/network/network_interface.cpp b/source/glest_game/network/network_interface.cpp index 7d6add3df..c74e51fe8 100644 --- a/source/glest_game/network/network_interface.cpp +++ b/source/glest_game/network/network_interface.cpp @@ -75,13 +75,14 @@ void NetworkInterface::sendMessage(NetworkMessage* networkMessage){ networkMessage->send(socket); } -NetworkMessageType NetworkInterface::getNextMessageType() +NetworkMessageType NetworkInterface::getNextMessageType(int waitMilliseconds) { Socket* socket= getSocket(false); int8 messageType= nmtInvalid; if(socket != NULL && - socket->hasDataToRead() == true) { + ((waitMilliseconds <= 0 && socket->hasDataToRead() == true) || + (waitMilliseconds > 0 && socket->hasDataToReadWithWait(waitMilliseconds) == true))) { //peek message type int dataSize = socket->getDataToRead(); if(dataSize >= sizeof(messageType)) { diff --git a/source/glest_game/network/network_interface.h b/source/glest_game/network/network_interface.h index 9414baba0..fdf4d8d7f 100644 --- a/source/glest_game/network/network_interface.h +++ b/source/glest_game/network/network_interface.h @@ -207,7 +207,7 @@ public: string getHostName() const {return Socket::getHostName();} virtual void sendMessage(NetworkMessage* networkMessage); - NetworkMessageType getNextMessageType(); + NetworkMessageType getNextMessageType(int waitMilliseconds=0); bool receiveMessage(NetworkMessage* networkMessage); virtual bool isConnected(); diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index cf0fb2321..087cf5bdc 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -1077,13 +1077,12 @@ bool Socket::hasDataToRead(PLATFORM_SOCKET socket) return bResult; } -bool Socket::hasDataToReadWithWait(int waitMilliseconds) -{ +bool Socket::hasDataToReadWithWait(int waitMilliseconds) { + MutexSafeWrapper safeMutex(dataSynchAccessorRead,CODE_AT_LINE); return Socket::hasDataToReadWithWait(sock,waitMilliseconds) ; } -bool Socket::hasDataToReadWithWait(PLATFORM_SOCKET socket,int waitMilliseconds) -{ +bool Socket::hasDataToReadWithWait(PLATFORM_SOCKET socket,int waitMilliseconds) { bool bResult = false; Chrono chono;