fix: replace O(n²) path dedup with O(1) hash set lookup

This commit is contained in:
Denis Angell
2026-05-04 18:26:29 +02:00
parent 8490206228
commit f4e1dc748b
3 changed files with 30 additions and 13 deletions

View File

@@ -111,6 +111,12 @@ public:
bool
operator!=(STPathElement const& t) const;
[[nodiscard]] std::size_t
hash() const noexcept
{
return hash_value_;
}
private:
static std::size_t
getHash(STPathElement const& element);

View File

@@ -41,6 +41,7 @@
#include <optional>
#include <ostream>
#include <string>
#include <unordered_set>
#include <vector>
namespace xrpl {
@@ -978,16 +979,10 @@ Pathfinder::isNoRippleOut(STPath const& currentPath)
}
void
addUniquePath(STPathSet& pathSet, STPath const& path)
addUniquePath(STPathSet& pathSet, std::unordered_set<STPath, STPathHash>& index, STPath const& path)
{
// TODO(tom): building an STPathSet this way is quadratic in the size
// of the STPathSet!
for (auto const& p : pathSet)
{
if (p == path)
return;
}
pathSet.pushBack(path);
if (index.insert(path).second)
pathSet.pushBack(path);
}
void
@@ -1021,7 +1016,7 @@ Pathfinder::addLink(
{ // non-default path to XRP destination
JLOG(j_.trace()) << "complete path found ax: "
<< currentPath.getJson(JsonOptions::KNone);
addUniquePath(completePaths_, currentPath);
addUniquePath(completePaths_, completePathsIndex_, currentPath);
}
}
else
@@ -1124,7 +1119,8 @@ Pathfinder::addLink(
{
JLOG(j_.trace()) << "complete path found ae: "
<< currentPath.getJson(JsonOptions::KNone);
addUniquePath(completePaths_, currentPath);
addUniquePath(
completePaths_, completePathsIndex_, currentPath);
}
}
else if (!bDestOnly)
@@ -1255,7 +1251,7 @@ Pathfinder::addLink(
// complete
JLOG(j_.trace()) << "complete path found bx: "
<< currentPath.getJson(JsonOptions::KNone);
addUniquePath(completePaths_, newPath);
addUniquePath(completePaths_, completePathsIndex_, newPath);
}
else
{
@@ -1301,7 +1297,7 @@ Pathfinder::addLink(
// complete
JLOG(j_.trace()) << "complete path found ba: "
<< currentPath.getJson(JsonOptions::KNone);
addUniquePath(completePaths_, newPath);
addUniquePath(completePaths_, completePathsIndex_, newPath);
}
else
{

View File

@@ -10,8 +10,22 @@
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STPathSet.h>
#include <unordered_set>
namespace xrpl {
struct STPathHash
{
std::size_t
operator()(STPath const& path) const noexcept
{
std::size_t h = path.size();
for (auto const& elem : path)
h ^= elem.hash() + 0x9e3779b9 + (h << 6) + (h >> 2);
return h;
}
};
/** Calculates payment paths.
The @ref RippleCalc determines the quality of the found paths.
@@ -187,6 +201,7 @@ private:
STPathElement source_;
STPathSet completePaths_;
std::unordered_set<STPath, STPathHash> completePathsIndex_;
std::vector<PathRank> pathRanks_;
std::map<PathType, STPathSet> paths_;