- attempt to improve performance when units are blocked badly (this is not backwards compatible with other builds, will create out of synch)

This commit is contained in:
Mark Vejvoda 2013-02-22 06:52:51 +00:00
parent b8f594fcf2
commit c63da54bbd
7 changed files with 152 additions and 8 deletions

View File

@ -218,7 +218,8 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
}
}
if(path->isStuck() == true && unit->getLastStuckPos() == finalPos &&
if(path->isStuck() == true &&
(unit->getLastStuckPos() == finalPos || path->getBlockCount() > 500) &&
unit->isLastStuckFrameWithinCurrentFrameTolerance() == true) {
//printf("$$$$ Unit STILL BLOCKED for [%d - %s]\n",unit->getId(),unit->getFullName().c_str());
@ -1418,6 +1419,31 @@ int PathFinder::findNodeIndex(Node *node, std::vector<Node> &nodeList) {
return index;
}
bool PathFinder::unitCannotMove(Unit *unit) {
bool unitImmediatelyBlocked = false;
// First check if unit currently blocked all around them, if so don't try to pathfind
const bool showConsoleDebugInfo = Config::getInstance().getBool("EnablePathfinderDistanceOutput","false");
const Vec2i unitPos = unit->getPos();
int failureCount = 0;
int cellCount = 0;
for(int i = -1; i <= 1; ++i) {
for(int j = -1; j <= 1; ++j) {
Vec2i pos = unitPos + Vec2i(i, j);
if(pos != unitPos) {
bool canUnitMoveToCell = map->aproxCanMove(unit, unitPos, pos);
if(canUnitMoveToCell == false) {
failureCount++;
}
cellCount++;
}
}
}
unitImmediatelyBlocked = (failureCount == cellCount);
return unitImmediatelyBlocked;
}
void PathFinder::saveGame(XmlNode *rootNode) {
std::map<string,string> mapTagReplacements;
XmlNode *pathfinderNode = rootNode->addChild("PathFinder");

View File

@ -164,6 +164,8 @@ public:
void removeUnitPrecache(Unit *unit);
void clearCaches();
bool unitCannotMove(Unit *unit);
int findNodeIndex(Node *node, Nodes &nodeList);
int findNodeIndex(Node *node, std::vector<Node> &nodeList);

View File

@ -3672,9 +3672,17 @@ void Unit::setLastStuckFrameToCurrentFrame() {
lastStuckFrame = getFrameCount();
}
bool Unit::isLastStuckFrameWithinCurrentFrameTolerance() const {
const int MIN_FRAME_ELAPSED_RETRY = 300;
bool result (getFrameCount() - lastStuckFrame <= MIN_FRAME_ELAPSED_RETRY);
bool Unit::isLastStuckFrameWithinCurrentFrameTolerance() {
//const int MIN_FRAME_ELAPSED_RETRY = 300;
const int MAX_BLOCKED_FRAME_THRESHOLD = 25000;
int MIN_FRAME_ELAPSED_RETRY = 6;
if(lastStuckFrame < MAX_BLOCKED_FRAME_THRESHOLD) {
MIN_FRAME_ELAPSED_RETRY = random.randRange(2,6);
}
else {
MIN_FRAME_ELAPSED_RETRY = random.randRange(6,8);
}
bool result (getFrameCount() - lastStuckFrame <= (MIN_FRAME_ELAPSED_RETRY * 100));
return result;
}

View File

@ -722,7 +722,7 @@ public:
std::string toString() const;
bool needToUpdate();
bool isLastStuckFrameWithinCurrentFrameTolerance() const;
bool isLastStuckFrameWithinCurrentFrameTolerance();
inline uint32 getLastStuckFrame() const { return lastStuckFrame; }
inline void setLastStuckFrame(uint32 value) { lastStuckFrame = value; }
void setLastStuckFrameToCurrentFrame();

View File

@ -106,7 +106,9 @@ UnitUpdater::~UnitUpdater() {
// ==================== progress skills ====================
//skill dependent actions
void UnitUpdater::updateUnit(Unit *unit) {
bool UnitUpdater::updateUnit(Unit *unit) {
bool processUnitCommand = false;
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
@ -153,6 +155,7 @@ void UnitUpdater::updateUnit(Unit *unit) {
if(update == true) {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
processUnitCommand = true;
updateUnitCommand(unit,-1);
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after updateUnitCommand()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
@ -282,6 +285,8 @@ void UnitUpdater::updateUnit(Unit *unit) {
}
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());
return processUnitCommand;
}
// ==================== progress commands ====================

View File

@ -102,7 +102,7 @@ public:
~UnitUpdater();
//update skills
void updateUnit(Unit *unit);
bool updateUnit(Unit *unit);
//update commands
void updateUnitCommand(Unit *unit, int frameIndex);

View File

@ -462,6 +462,12 @@ void World::updateAllTilesetObjects() {
}
void World::updateAllFactionUnits() {
bool showPerfStats = Config::getInstance().getBool("ShowPerfStats","false");
Chrono chronoPerf;
if(showPerfStats) chronoPerf.start();
char perfBuf[8096]="";
std::vector<string> perfList;
scriptManager->onTimerTriggerEvent();
// Prioritize grouped command units so closest units to target go first
@ -491,6 +497,11 @@ void World::updateAllFactionUnits() {
faction->clearAproxCanMoveSoonCached();
}
if(showPerfStats) {
sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
perfList.push_back(perfBuf);
}
Chrono chrono;
chrono.start();
@ -500,6 +511,12 @@ void World::updateAllFactionUnits() {
bool slavesCompleted = masterController.waitTillSlavesTrigger(20000);
if(SystemFlags::VERBOSE_MODE_ENABLED && chrono.getMillis() >= 10) printf("In [%s::%s Line: %d] *** Faction thread preprocessing took [%lld] msecs for %d factions for frameCount = %d slavesCompleted = %d.\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),factionCount,frameCount,slavesCompleted);
if(showPerfStats) {
sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
perfList.push_back(perfBuf);
}
}
else {
// Signal the faction threads to do any pre-processing
@ -508,6 +525,11 @@ void World::updateAllFactionUnits() {
faction->signalWorkerThread(frameCount);
}
if(showPerfStats) {
sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
perfList.push_back(perfBuf);
}
bool workThreadsFinished = false;
Chrono chrono;
chrono.start();
@ -527,14 +549,32 @@ void World::updateAllFactionUnits() {
}
}
if(showPerfStats) {
sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
perfList.push_back(perfBuf);
}
if(SystemFlags::VERBOSE_MODE_ENABLED && chrono.getMillis() >= 10) printf("In [%s::%s Line: %d] *** Faction thread preprocessing took [%lld] msecs for %d factions for frameCount = %d.\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),factionCount,frameCount);
}
if(showPerfStats) {
sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
perfList.push_back(perfBuf);
}
//units
Chrono chronoPerfUnit;
int totalUnitsChecked = 0;
int totalUnitsProcessed = 0;
for(int i = 0; i < factionCount; ++i) {
Faction *faction = getFaction(i);
faction->clearUnitsPathfinding();
std::map<CommandClass,int> mapCommandCount;
std::map<SkillClass,int> mapSkillCount;
int unitCountStuck = 0;
int unitCountUpdated = 0;
int unitCount = faction->getUnitCount();
for(int j = 0; j < unitCount; ++j) {
Unit *unit = faction->getUnit(j);
@ -542,7 +582,70 @@ void World::updateAllFactionUnits() {
throw megaglest_runtime_error("unit == NULL");
}
unitUpdater.updateUnit(unit);
CommandClass unitCommandClass = ccCount;
if(unit->getCurrCommand() != NULL) {
unitCommandClass = unit->getCurrCommand()->getCommandType()->getClass();
}
SkillClass unitSkillClass = scCount;
if(unit->getCurrSkill() != NULL) {
unitSkillClass = unit->getCurrSkill()->getClass();
}
if(showPerfStats) chronoPerfUnit.start();
int unitBlockCount = unit->getPath()->getBlockCount();
bool isStuck = unit->getPath()->isStuck();
bool isStuckWithinTolerance = unit->isLastStuckFrameWithinCurrentFrameTolerance();
uint32 lastStuckFrame = unit->getLastStuckFrame();
if(unitUpdater.updateUnit(unit) == true) {
unitCountUpdated++;
if(unit->getLastStuckFrame() == frameCount) {
unitCountStuck++;
}
mapCommandCount[unitCommandClass] = mapCommandCount[unitCommandClass] + 1;
mapSkillCount[unitSkillClass] = mapSkillCount[unitSkillClass] + 1;
}
totalUnitsChecked++;
if(showPerfStats && chronoPerfUnit.getMillis() >= 10) {
sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER " stuck: %d [%d] for unit:\n%sBEFORE unitBlockCount = %d, AFTER = %d, BEFORE lastStuckFrame = %u, AFTER: %u\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerfUnit.getMillis(),isStuck,isStuckWithinTolerance,unit->toString().c_str(),unitBlockCount,unit->getPath()->getBlockCount(),lastStuckFrame,unit->getLastStuckFrame());
perfList.push_back(perfBuf);
}
}
totalUnitsProcessed += unitCountUpdated;
if(showPerfStats) {
sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER " faction: %d / %d unitCount = %d unitCountUpdated = %d unitCountStuck = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis(),i+1,factionCount,unitCount,unitCountUpdated,unitCountStuck);
perfList.push_back(perfBuf);
for(std::map<CommandClass,int>::iterator iterMap = mapCommandCount.begin();
iterMap != mapCommandCount.end(); ++iterMap) {
sprintf(perfBuf,"Command class = %d, count = %d\n",iterMap->first,iterMap->second);
perfList.push_back(perfBuf);
}
for(std::map<SkillClass,int>::iterator iterMap = mapSkillCount.begin();
iterMap != mapSkillCount.end(); ++iterMap) {
sprintf(perfBuf,"Skill class = %d, count = %d\n",iterMap->first,iterMap->second);
perfList.push_back(perfBuf);
}
}
}
if(showPerfStats) {
sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER " totalUnitsProcessed = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis(),totalUnitsProcessed);
perfList.push_back(perfBuf);
}
if(showPerfStats && chronoPerf.getMillis() >= 50) {
for(unsigned int x = 0; x < perfList.size(); ++x) {
printf("%s",perfList[x].c_str());
}
}