1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

Use containers with pre-allocations to improve pathfinding speed

This commit is contained in:
Ivan Savenko
2024-07-03 18:06:56 +00:00
parent 24b77b0972
commit 40f17d654d
5 changed files with 29 additions and 22 deletions

View File

@@ -320,11 +320,9 @@ void AINodeStorage::calculateNeighbours(
const PathfinderConfig * pathfinderConfig, const PathfinderConfig * pathfinderConfig,
const CPathfinderHelper * pathfinderHelper) const CPathfinderHelper * pathfinderHelper)
{ {
std::vector<int3> accessibleNeighbourTiles; NeighbourTilesVector accessibleNeighbourTiles;
result.clear(); result.clear();
accessibleNeighbourTiles.reserve(8);
pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source); pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source);
const AIPathNode * srcNode = getAINode(source.node); const AIPathNode * srcNode = getAINode(source.node);

View File

@@ -162,10 +162,9 @@ void AINodeStorage::calculateNeighbours(
const PathfinderConfig * pathfinderConfig, const PathfinderConfig * pathfinderConfig,
const CPathfinderHelper * pathfinderHelper) const CPathfinderHelper * pathfinderHelper)
{ {
std::vector<int3> accessibleNeighbourTiles; NeighbourTilesVector accessibleNeighbourTiles;
result.clear(); result.clear();
accessibleNeighbourTiles.reserve(8);
pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source); pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source);

View File

@@ -49,7 +49,7 @@ bool CPathfinderHelper::canMoveFromNode(const PathNodeInfo & source) const
return true; return true;
} }
void CPathfinderHelper::calculateNeighbourTiles(std::vector<int3> & result, const PathNodeInfo & source) const void CPathfinderHelper::calculateNeighbourTiles(NeighbourTilesVector & result, const PathNodeInfo & source) const
{ {
result.clear(); result.clear();
@@ -239,9 +239,9 @@ void CPathfinder::calculatePaths()
logAi->trace("CPathfinder finished with %s iterations", std::to_string(counter)); logAi->trace("CPathfinder finished with %s iterations", std::to_string(counter));
} }
std::vector<int3> CPathfinderHelper::getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const TeleporterTilesVector CPathfinderHelper::getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const
{ {
std::vector<int3> allowedExits; TeleporterTilesVector allowedExits;
for(const auto & objId : getTeleportChannelExits(channelID, hero->tempOwner)) for(const auto & objId : getTeleportChannelExits(channelID, hero->tempOwner))
{ {
@@ -262,9 +262,9 @@ std::vector<int3> CPathfinderHelper::getAllowedTeleportChannelExits(const Telepo
return allowedExits; return allowedExits;
} }
std::vector<int3> CPathfinderHelper::getCastleGates(const PathNodeInfo & source) const TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & source) const
{ {
std::vector<int3> allowedExits; TeleporterTilesVector allowedExits;
auto towns = getPlayerState(hero->tempOwner)->towns; auto towns = getPlayerState(hero->tempOwner)->towns;
for(const auto & town : towns) for(const auto & town : towns)
@@ -279,9 +279,9 @@ std::vector<int3> CPathfinderHelper::getCastleGates(const PathNodeInfo & source)
return allowedExits; return allowedExits;
} }
std::vector<int3> CPathfinderHelper::getTeleportExits(const PathNodeInfo & source) const TeleporterTilesVector CPathfinderHelper::getTeleportExits(const PathNodeInfo & source) const
{ {
std::vector<int3> teleportationExits; TeleporterTilesVector teleportationExits;
const auto * objTeleport = dynamic_cast<const CGTeleport *>(source.nodeObject); const auto * objTeleport = dynamic_cast<const CGTeleport *>(source.nodeObject);
if(isAllowedTeleportEntrance(objTeleport)) if(isAllowedTeleportEntrance(objTeleport))
@@ -578,7 +578,7 @@ int CPathfinderHelper::getMaxMovePoints(const EPathfindingLayer & layer) const
void CPathfinderHelper::getNeighbours( void CPathfinderHelper::getNeighbours(
const TerrainTile & srcTile, const TerrainTile & srcTile,
const int3 & srcCoord, const int3 & srcCoord,
std::vector<int3> & vec, NeighbourTilesVector & vec,
const boost::logic::tribool & onLand, const boost::logic::tribool & onLand,
const bool limitCoastSailing) const const bool limitCoastSailing) const
{ {
@@ -702,8 +702,8 @@ int CPathfinderHelper::getMovementCost(
constexpr auto maxCostOfOneStep = static_cast<int>(175 * M_SQRT2); // diagonal move on Swamp - 247 MP constexpr auto maxCostOfOneStep = static_cast<int>(175 * M_SQRT2); // diagonal move on Swamp - 247 MP
if(checkLast && left > 0 && left <= maxCostOfOneStep) //it might be the last tile - if no further move possible we take all move points if(checkLast && left > 0 && left <= maxCostOfOneStep) //it might be the last tile - if no further move possible we take all move points
{ {
std::vector<int3> vec; NeighbourTilesVector vec;
vec.reserve(8); //optimization
getNeighbours(*dt, dst, vec, ct->terType->isLand(), true); getNeighbours(*dt, dst, vec, ct->terType->isLand(), true);
for(const auto & elem : vec) for(const auto & elem : vec)
{ {

View File

@@ -13,12 +13,23 @@
#include "../IGameCallback.h" #include "../IGameCallback.h"
#include "../bonuses/BonusEnum.h" #include "../bonuses/BonusEnum.h"
#include <boost/container/static_vector.hpp>
#include <boost/container/small_vector.hpp>
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
class CGWhirlpool; class CGWhirlpool;
struct TurnInfo; struct TurnInfo;
struct PathfinderOptions; struct PathfinderOptions;
// Optimized storage - tile can have 0-8 neighbour tiles
// static_vector uses fixed, preallocated storage (capacity) and dynamic size
// this avoid dynamic allocations on huge number of neighbour list queries
using NeighbourTilesVector = boost::container::static_vector<int3, 8>;
// Optimized storage to minimize dynamic allocations - most of teleporters have only one exit, but some may have more (premade maps, castle gates)
using TeleporterTilesVector = boost::container::small_vector<int3, 4>;
class DLL_LINKAGE CPathfinder class DLL_LINKAGE CPathfinder
{ {
public: public:
@@ -87,22 +98,22 @@ public:
bool hasBonusOfType(BonusType type) const; bool hasBonusOfType(BonusType type) const;
int getMaxMovePoints(const EPathfindingLayer & layer) const; int getMaxMovePoints(const EPathfindingLayer & layer) const;
std::vector<int3> getCastleGates(const PathNodeInfo & source) const; TeleporterTilesVector getCastleGates(const PathNodeInfo & source) const;
bool isAllowedTeleportEntrance(const CGTeleport * obj) const; bool isAllowedTeleportEntrance(const CGTeleport * obj) const;
std::vector<int3> getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const; TeleporterTilesVector getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const;
bool addTeleportTwoWay(const CGTeleport * obj) const; bool addTeleportTwoWay(const CGTeleport * obj) const;
bool addTeleportOneWay(const CGTeleport * obj) const; bool addTeleportOneWay(const CGTeleport * obj) const;
bool addTeleportOneWayRandom(const CGTeleport * obj) const; bool addTeleportOneWayRandom(const CGTeleport * obj) const;
bool addTeleportWhirlpool(const CGWhirlpool * obj) const; bool addTeleportWhirlpool(const CGWhirlpool * obj) const;
bool canMoveBetween(const int3 & a, const int3 & b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility) bool canMoveBetween(const int3 & a, const int3 & b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
void calculateNeighbourTiles(std::vector<int3> & result, const PathNodeInfo & source) const; void calculateNeighbourTiles(NeighbourTilesVector & result, const PathNodeInfo & source) const;
std::vector<int3> getTeleportExits(const PathNodeInfo & source) const; TeleporterTilesVector getTeleportExits(const PathNodeInfo & source) const;
void getNeighbours( void getNeighbours(
const TerrainTile & srcTile, const TerrainTile & srcTile,
const int3 & srcCoord, const int3 & srcCoord,
std::vector<int3> & vec, NeighbourTilesVector & vec,
const boost::logic::tribool & onLand, const boost::logic::tribool & onLand,
const bool limitCoastSailing) const; const bool limitCoastSailing) const;

View File

@@ -67,10 +67,9 @@ void NodeStorage::calculateNeighbours(
const PathfinderConfig * pathfinderConfig, const PathfinderConfig * pathfinderConfig,
const CPathfinderHelper * pathfinderHelper) const CPathfinderHelper * pathfinderHelper)
{ {
std::vector<int3> accessibleNeighbourTiles; NeighbourTilesVector accessibleNeighbourTiles;
result.clear(); result.clear();
accessibleNeighbourTiles.reserve(8);
pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source); pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source);