From 2d6cda1f6fc561a5eb322e74fea98d90fe3f741c Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Wed, 9 May 2012 23:56:14 +0000 Subject: [PATCH] - more pathfinder tweaks to try improve performance --- source/glest_game/ai/fast_path_finder.cpp | 26 +++++++------- source/glest_game/ai/path_finder.cpp | 6 ++-- source/glest_game/type_instances/faction.cpp | 26 ++++++++++++++ source/glest_game/types/command_type.h | 22 ++++++++++++ source/glest_game/world/unit_updater.cpp | 37 +++++++++++++++----- source/glest_game/world/world.cpp | 12 ++----- source/glest_game/world/world.h | 8 ++++- 7 files changed, 103 insertions(+), 34 deletions(-) diff --git a/source/glest_game/ai/fast_path_finder.cpp b/source/glest_game/ai/fast_path_finder.cpp index 3d82c008..1b3eeeac 100644 --- a/source/glest_game/ai/fast_path_finder.cpp +++ b/source/glest_game/ai/fast_path_finder.cpp @@ -446,7 +446,7 @@ public: // methods } // Set Start and goal states - void SetStartAndGoalStates( UserState &Start, UserState &Goal, void *userData ) { + inline void SetStartAndGoalStates( UserState &Start, UserState &Goal, void *userData ) { this->userData = userData; // Reinit nodes pool after previous searches @@ -486,7 +486,7 @@ public: // methods } // Advances search one step - SearchState SearchStep(unsigned int &searchCount) { + inline SearchState SearchStep(unsigned int &searchCount) { searchCount = 0; // Firstly break if the user has not initialised the search assert( (m_State > SEARCH_STATE_NOT_INITIALISED) && (m_State < SEARCH_STATE_INVALID) ); @@ -643,7 +643,7 @@ public: // methods // User calls this to add a successor to a list of successors // when expanding the search frontier - bool AddSuccessor( UserState &State ) { + inline bool AddSuccessor( UserState &State ) { Node *node = AllocateNode(); if( node ) { node->m_UserState = State; @@ -659,7 +659,7 @@ public: // methods // Free the solution nodes // This is done to clean up all used Node memory when you are done with the // search - void FreeSolutionNodes() { + inline void FreeSolutionNodes() { Node *n = m_Start; if( m_Start && m_Start->child ) { do { @@ -688,7 +688,7 @@ public: // methods // Functions for traversing the solution // Get start node - UserState *GetSolutionStart() { + inline UserState *GetSolutionStart() { m_CurrentSolutionNode = m_Start; if( m_Start ) { return &m_Start->m_UserState; @@ -699,7 +699,7 @@ public: // methods } // Get next node - UserState *GetSolutionNext() { + inline UserState *GetSolutionNext() { if( m_CurrentSolutionNode ) { if( m_CurrentSolutionNode->child ) { m_CurrentSolutionNode = m_CurrentSolutionNode->child; @@ -711,7 +711,7 @@ public: // methods } // Get end node - UserState *GetSolutionEnd() { + inline UserState *GetSolutionEnd() { m_CurrentSolutionNode = m_Goal; if( m_Goal ) { return &m_Goal->m_UserState; @@ -722,7 +722,7 @@ public: // methods } // Step solution iterator backwards - UserState *GetSolutionPrev() { + inline UserState *GetSolutionPrev() { if( m_CurrentSolutionNode ) { if( m_CurrentSolutionNode->parent ) { m_CurrentSolutionNode = m_CurrentSolutionNode->parent; @@ -1054,7 +1054,7 @@ public: ~FastAstar(void) { } - void startSearch(AI_Node *from,AI_Node *to,void *userData) { + inline void startSearch(AI_Node *from,AI_Node *to,void *userData) { mSolution.clear(); MapSearchNode start(from); MapSearchNode end(to); @@ -1062,11 +1062,11 @@ public: mAstarSearch.SetStartAndGoalStates(start,end,userData); } - SearchState getLastSearchState() { + inline SearchState getLastSearchState() { return lastSearchState; } - bool searchStep(unsigned int &searchCount) { + inline bool searchStep(unsigned int &searchCount) { bool ret = false; SearchState state = mAstarSearch.SearchStep(searchCount); @@ -1087,7 +1087,7 @@ public: mSolution.push_back(ai); node = mAstarSearch.GetSolutionNext(); } - mAstarSearch.FreeSolutionNodes(); + //mAstarSearch.FreeSolutionNodes(); } ret = true; break; @@ -1105,7 +1105,7 @@ public: return ret; } - AI_Node ** getSolution(unsigned int &count) { + inline AI_Node ** getSolution(unsigned int &count) { AI_Node **ret = 0; count = 0; if ( !mSolution.empty() ) { diff --git a/source/glest_game/ai/path_finder.cpp b/source/glest_game/ai/path_finder.cpp index 9292b0a9..1bfa02d7 100644 --- a/source/glest_game/ai/path_finder.cpp +++ b/source/glest_game/ai/path_finder.cpp @@ -120,17 +120,19 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu unit->setCurrentPathFinderDesiredFinalPos(finalPos); + //printf("Unit Pathfind Unit [%d - %s] from = %s to = %s frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),unit->getPos().getString().c_str(),finalPos.getString().c_str(),frameIndex); + if(frameIndex >= 0) { clearUnitPrecache(unit); } - else { + //else { if(unit->getFaction()->canUnitsPathfind() == true) { unit->getFaction()->addUnitToPathfindingList(unit->getId()); } else { return tsBlocked; } - } + //} // if(frameIndex != factions[unit->getFactionIndex()].lastFromToNodeListFrame) { // if(factions[unit->getFactionIndex()].mapFromToNodeList.size() > 0) { diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index b4eb4919..49f4ab29 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -288,6 +288,9 @@ void FactionThread::execute() { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] ****************** STARTING worker thread this = %p\n",__FILE__,__FUNCTION__,__LINE__,this); + bool minorDebugPerformance = false; + Chrono chrono; + //unsigned int idx = 0; for(;this->faction != NULL;) { if(getQuitStatus() == true) { @@ -323,6 +326,10 @@ void FactionThread::execute() { } MutexSafeWrapper safeMutex(faction->getUnitMutex(),string(__FILE__) + "_" + intToStr(__LINE__)); + + //if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); + if(minorDebugPerformance) chrono.start(); + int unitCount = faction->getUnitCount(); for(int j = 0; j < unitCount; ++j) { Unit *unit = faction->getUnit(j); @@ -330,12 +337,27 @@ void FactionThread::execute() { throw megaglest_runtime_error("unit == NULL"); } + int64 elapsed1 = 0; + if(minorDebugPerformance) elapsed1 = chrono.getMillis(); + bool update = unit->needToUpdate(); + + if(minorDebugPerformance && (chrono.getMillis() - elapsed1) >= 1) printf("Faction [%d - %s] #1-unit threaded updates on frame: %d for [%d] unit # %d, unitCount = %d, took [%lld] msecs\n",faction->getStartLocationIndex(),faction->getType()->getName().c_str(),frameIndex.first,faction->getUnitPathfindingListCount(),j,unitCount,(long long int)chrono.getMillis() - elapsed1); + //update = true; if(update == true) { + + int64 elapsed2 = 0; + if(minorDebugPerformance) elapsed2 = chrono.getMillis(); + world->getUnitUpdater()->updateUnitCommand(unit,frameIndex.first); + + if(minorDebugPerformance && (chrono.getMillis() - elapsed2) >= 1) printf("Faction [%d - %s] #2-unit threaded updates on frame: %d for [%d] unit # %d, unitCount = %d, took [%lld] msecs\n",faction->getStartLocationIndex(),faction->getType()->getName().c_str(),frameIndex.first,faction->getUnitPathfindingListCount(),j,unitCount,(long long int)chrono.getMillis() - elapsed2); } } + + if(minorDebugPerformance && chrono.getMillis() >= 1) printf("Faction [%d - %s] threaded updates on frame: %d for [%d] units took [%lld] msecs\n",faction->getStartLocationIndex(),faction->getType()->getName().c_str(),frameIndex.first,faction->getUnitPathfindingListCount(),(long long int)chrono.getMillis()); + safeMutex.ReleaseLock(); setTaskCompleted(frameIndex.first); @@ -468,17 +490,21 @@ int Faction::getUnitMovingListCount() { } void Faction::addUnitToPathfindingList(int unitId) { + //printf("ADD (1) Faction [%d - %s] threaded updates for [%d] units\n",this->getStartLocationIndex(),this->getType()->getName().c_str(),unitsPathfindingList.size()); unitsPathfindingList[unitId] = getWorld()->getFrameCount(); + //printf("ADD (2) Faction [%d - %s] threaded updates for [%d] units\n",this->getStartLocationIndex(),this->getType()->getName().c_str(),unitsPathfindingList.size()); } void Faction::removeUnitFromPathfindingList(int unitId) { unitsPathfindingList.erase(unitId); } int Faction::getUnitPathfindingListCount() { + //printf("GET Faction [%d - %s] threaded updates for [%d] units\n",this->getStartLocationIndex(),this->getType()->getName().c_str(),unitsPathfindingList.size()); return unitsPathfindingList.size(); } void Faction::clearUnitsPathfinding() { + //printf("CLEAR Faction [%d - %s] threaded updates for [%d] units\n",this->getStartLocationIndex(),this->getType()->getName().c_str(),unitsPathfindingList.size()); unitsPathfindingList.clear(); } diff --git a/source/glest_game/types/command_type.h b/source/glest_game/types/command_type.h index 0063e0b2..3ab26648 100644 --- a/source/glest_game/types/command_type.h +++ b/source/glest_game/types/command_type.h @@ -104,6 +104,7 @@ public: } //Priority: commands of higher priority will cancel commands of lower priority virtual int getTypePriority() const {return 10;} + virtual bool usesPathfinder() const= 0; //get CommandClass getClass() const; @@ -131,6 +132,8 @@ public: virtual int getTypePriority() const {return 100000;} //get const StopSkillType *getStopSkillType() const {return stopSkillType;}; + + virtual bool usesPathfinder() const { return false; } }; @@ -153,6 +156,8 @@ public: //get const MoveSkillType *getMoveSkillType() const {return moveSkillType;}; + + virtual bool usesPathfinder() const { return true; } }; @@ -178,6 +183,8 @@ public: //get const MoveSkillType * getMoveSkillType() const {return moveSkillType;} const AttackSkillType * getAttackSkillType() const {return attackSkillType;} + + virtual bool usesPathfinder() const { return true; } }; // ======================================= @@ -201,6 +208,8 @@ public: //get const StopSkillType * getStopSkillType() const {return stopSkillType;} const AttackSkillType * getAttackSkillType() const {return attackSkillType;} + + virtual bool usesPathfinder() const { return false; } }; @@ -233,6 +242,8 @@ public: const UnitType * getBuilding(int i) const {return buildings[i];} StaticSound *getStartSound() const {return startSounds.getRandSound();} StaticSound *getBuiltSound() const {return builtSounds.getRandSound();} + + virtual bool usesPathfinder() const { return true; } }; @@ -270,6 +281,8 @@ public: int getHarvestedResourceCount() const {return harvestedResources.size();} const ResourceType* getHarvestedResource(int i) const {return harvestedResources[i];} bool canHarvest(const ResourceType *resourceType) const; + + virtual bool usesPathfinder() const { return true; } }; @@ -301,6 +314,7 @@ public: int getRepairCount() const {return repairableUnits.size();} const UnitType * getRepair(int i) const {return repairableUnits[i];} + virtual bool usesPathfinder() const { return true; } }; @@ -329,6 +343,8 @@ public: //get const ProduceSkillType *getProduceSkillType() const {return produceSkillType;} const UnitType *getProducedUnit() const {return producedUnit;} + + virtual bool usesPathfinder() const { return false; } }; @@ -357,6 +373,8 @@ public: //get const UpgradeSkillType *getUpgradeSkillType() const {return upgradeSkillType;} const UpgradeType *getProducedUpgrade() const {return producedUpgrade;} + + virtual bool usesPathfinder() const { return false; } }; // =============================== @@ -387,6 +405,8 @@ public: const UnitType *getMorphUnit() const {return morphUnit;} int getDiscount() const {return discount;} bool getIgnoreResourceRequirements() const {return ignoreResourceRequirements;} + + virtual bool usesPathfinder() const { return false; } }; // =============================== @@ -405,6 +425,8 @@ public: std::map > > &loadedFileList, string parentLoader); virtual string getDesc(const TotalUpgrade *totalUpgrade) const; virtual string toString() const; + + virtual bool usesPathfinder() const { return false; } }; // =============================== diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index 2b9cf698..9f85805a 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -297,20 +297,38 @@ void UnitUpdater::updateUnit(Unit *unit) { //VERY IMPORTANT: compute next state depending on the first order of the list void UnitUpdater::updateUnitCommand(Unit *unit, int frameIndex) { - // Clear previous cached unit data - if(frameIndex >= 0) { - clearUnitPrecache(unit); - } - + bool minorDebugPerformance = false; Chrono chrono; - if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); + if((minorDebugPerformance == true && frameIndex > 0) || SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); //if unit has command process it - if(unit->anyCommand()) { + bool hasCommand = (unit->anyCommand()); + + if((minorDebugPerformance && frameIndex > 0) && chrono.getMillis() >= 1) printf("UnitUpdate [%d - %s] #1-unit threaded updates on frame: %d took [%lld] msecs\n",unit->getId(),unit->getType()->getName().c_str(),frameIndex,(long long int)chrono.getMillis()); + + int64 elapsed1 = 0; + if(minorDebugPerformance && frameIndex > 0) elapsed1 = chrono.getMillis(); + + if(hasCommand == true) { if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unit [%s] has command [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str(), unit->getCurrCommand()->toString().c_str()); - CommandClass cc = unit->getCurrCommand()->getCommandType()->commandTypeClass; - unit->getCurrCommand()->getCommandType()->update(this, unit, frameIndex); + bool commandUsesPathFinder = (frameIndex < 0); + if(frameIndex > 0) { + commandUsesPathFinder = unit->getCurrCommand()->getCommandType()->usesPathfinder(); + + // Clear previous cached unit data + if(commandUsesPathFinder == true) { + clearUnitPrecache(unit); + } + } + if(commandUsesPathFinder == true) { + unit->getCurrCommand()->getCommandType()->update(this, unit, frameIndex); + } + + if((minorDebugPerformance && frameIndex > 0) && (chrono.getMillis() - elapsed1) >= 1) { + //CommandClass cc = unit->getCurrCommand()->getCommandType()->commandTypeClass; + printf("UnitUpdate [%d - %s] #2-unit threaded updates on frame: %d commandUsesPathFinder = %d took [%lld] msecs\nCommand: %s\n",unit->getId(),unit->getType()->getName().c_str(),frameIndex,commandUsesPathFinder,(long long int)chrono.getMillis() - elapsed1,unit->getCurrCommand()->toString().c_str()); + } } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); @@ -330,6 +348,7 @@ void UnitUpdater::updateUnitCommand(Unit *unit, int frameIndex) { } } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + if((minorDebugPerformance && frameIndex > 0) && chrono.getMillis() >= 1) printf("UnitUpdate [%d - %s] #3-unit threaded updates on frame: %d took [%lld] msecs\n",unit->getId(),unit->getType()->getName().c_str(),frameIndex,(long long int)chrono.getMillis()); } // ==================== updateStop ==================== diff --git a/source/glest_game/world/world.cpp b/source/glest_game/world/world.cpp index c2b7479e..2d6f4842 100644 --- a/source/glest_game/world/world.cpp +++ b/source/glest_game/world/world.cpp @@ -375,7 +375,7 @@ void World::updateAllFactionUnits() { // Prioritize grouped command units so closest units to target go first // units int factionCount = getFactionCount(); - + //printf("===== STARTING Frame: %d\n",frameCount); // Config &config= Config::getInstance(); // bool sortedUnitsAllowed = config.getBool("AllowGroupedUnitCommands","true"); // @@ -445,6 +445,8 @@ void World::updateAllFactionUnits() { throw megaglest_runtime_error("faction == NULL"); } + faction->clearUnitsPathfinding(); + int unitCount = faction->getUnitCount(); for(int j = 0; j < unitCount; ++j) { Unit *unit = faction->getUnit(j); @@ -575,14 +577,6 @@ bool World::canTickWorld() const { return needToTick; } -int World::getUpdateFps(int factionIndex) const { - int result = GameConstants::updateFps; - //if(factionIndex != -1 && staggeredFactionUpdates == true) { - // result = (GameConstants::updateFps / GameConstants::maxPlayers); - //} - return result; -} - bool World::canTickFaction(int factionIdx) { int factionUpdateInterval = (GameConstants::updateFps / GameConstants::maxPlayers); int expectedFactionIdx = (frameCount / factionUpdateInterval) -1; diff --git a/source/glest_game/world/world.h b/source/glest_game/world/world.h index 226604bb..9497ae8f 100644 --- a/source/glest_game/world/world.h +++ b/source/glest_game/world/world.h @@ -265,7 +265,13 @@ public: void setFogOfWar(bool value); std::string DumpWorldToLog(bool consoleBasicInfoOnly = false) const; - int getUpdateFps(int factionIndex) const; + inline int getUpdateFps(int factionIndex) const { + int result = GameConstants::updateFps; + //if(factionIndex != -1 && staggeredFactionUpdates == true) { + // result = (GameConstants::updateFps / GameConstants::maxPlayers); + //} + return result; + } bool canTickWorld() const; void exploreCells(const Vec2i &newPos, int sightRange, int teamIndex);