mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-02 16:26:48 +00:00
fix: replace O(n²) path dedup with O(1) hash set lookup
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user