mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Optimize pathfinding operations (RIPD-537):
* Calculate and cache Account hashes without holding locks. * Fast hash-based path element comparison. * Use emplace instead of find/insert
This commit is contained in:
@@ -500,19 +500,18 @@ int Pathfinder::getPathsOut (
|
||||
Currency const& currencyID, Account const& accountID,
|
||||
bool isDstCurrency, Account const& dstAccount)
|
||||
{
|
||||
Issue issue (currencyID, accountID);
|
||||
auto it = mPathsOutCountMap.find (issue);
|
||||
Issue const issue (currencyID, accountID);
|
||||
|
||||
if (it != mPathsOutCountMap.end ())
|
||||
return it->second;
|
||||
auto it = mPathsOutCountMap.emplace (issue, 0);
|
||||
|
||||
auto sleAccount = mLedger->getSLEi (
|
||||
Ledger::getAccountRootIndex (accountID));
|
||||
// If it was already present, return the stored number of paths
|
||||
if (!it.second)
|
||||
return it.first->second;
|
||||
|
||||
auto sleAccount = mLedger->getSLEi (Ledger::getAccountRootIndex (accountID));
|
||||
|
||||
if (!sleAccount)
|
||||
{
|
||||
mPathsOutCountMap[issue] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aFlags = sleAccount->getFieldU32(sfFlags);
|
||||
bool const bAuthRequired = (aFlags & lsfRequireAuth) != 0;
|
||||
@@ -523,7 +522,7 @@ int Pathfinder::getPathsOut (
|
||||
|
||||
if (!bFrozen)
|
||||
{
|
||||
count = getApp().getOrderBookDB().getBookSize({currencyID, accountID});
|
||||
count = getApp().getOrderBookDB().getBookSize(issue);
|
||||
|
||||
for (auto const& item : mRLCache->getRippleLines (accountID))
|
||||
{
|
||||
@@ -552,7 +551,7 @@ int Pathfinder::getPathsOut (
|
||||
++count;
|
||||
}
|
||||
}
|
||||
mPathsOutCountMap[issue] = count;
|
||||
it.first->second = count;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,25 +24,19 @@ RippleLineCache::RippleLineCache (Ledger::ref l)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<RippleState::pointer> const&
|
||||
RippleLineCache::RippleStateVector const&
|
||||
RippleLineCache::getRippleLines (Account const& accountID)
|
||||
{
|
||||
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
auto it = mRLMap.find (accountID);
|
||||
if (it != mRLMap.end ())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// It's not in the cache, so build it
|
||||
auto lines = ripple::getRippleStateItems (accountID, mLedger);
|
||||
AccountKey key (accountID);
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
// We must return a reference to the cached version
|
||||
return mRLMap.emplace (accountID, std::move (lines)).first->second;
|
||||
auto it = mRLMap.emplace (key, RippleStateVector ());
|
||||
|
||||
if (it.second)
|
||||
it.first->second = ripple::getRippleStateItems (accountID, mLedger);
|
||||
|
||||
return it.first->second;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace ripple {
|
||||
class RippleLineCache
|
||||
{
|
||||
public:
|
||||
typedef std::vector <RippleState::pointer> RippleStateVector;
|
||||
typedef std::shared_ptr <RippleLineCache> pointer;
|
||||
typedef pointer const& ref;
|
||||
|
||||
@@ -46,7 +47,55 @@ private:
|
||||
|
||||
Ledger::pointer mLedger;
|
||||
|
||||
hash_map <Account, std::vector <RippleState::pointer>> mRLMap;
|
||||
struct AccountKey
|
||||
{
|
||||
Account account_;
|
||||
std::size_t hash_value_;
|
||||
|
||||
AccountKey (Account const& account)
|
||||
: account_ (account)
|
||||
, hash_value_ (beast::hardened_hash<>{}(account))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AccountKey (AccountKey const& other)
|
||||
: account_ (other.account_)
|
||||
, hash_value_ (other.hash_value_)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AccountKey& operator=(AccountKey const& other)
|
||||
{
|
||||
account_ = other.account_;
|
||||
hash_value_ = other.hash_value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator== (AccountKey const& lhs) const
|
||||
{
|
||||
return hash_value_ == lhs.hash_value_ &&
|
||||
account_ == lhs.account_;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
get_hash () const
|
||||
{
|
||||
return hash_value_;
|
||||
}
|
||||
|
||||
struct Hash
|
||||
{
|
||||
std::size_t
|
||||
operator () (AccountKey const& key) const noexcept
|
||||
{
|
||||
return key.get_hash ();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
hash_map <AccountKey, RippleStateVector, AccountKey::Hash> mRLMap;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -187,6 +187,29 @@ void STAccount::setValueNCA (RippleAddress const& nca)
|
||||
setValueH160 (nca.getAccountID ());
|
||||
}
|
||||
|
||||
std::size_t
|
||||
STPathElement::get_hash (STPathElement const& element)
|
||||
{
|
||||
std::size_t hash_account = 2654435761;
|
||||
std::size_t hash_currency = 2654435761;
|
||||
std::size_t hash_issuer = 2654435761;
|
||||
|
||||
// NIKB NOTE: This doesn't have to be a secure hash as speed is more
|
||||
// important. We don't even really need to fully hash the whole
|
||||
// base_uint here, as a few bytes would do for our use.
|
||||
|
||||
for (auto const x : element.getAccountID ())
|
||||
hash_account += (hash_account * 257) ^ x;
|
||||
|
||||
for (auto const x : element.getCurrency ())
|
||||
hash_currency += (hash_currency * 509) ^ x;
|
||||
|
||||
for (auto const x : element.getIssuerID ())
|
||||
hash_issuer += (hash_issuer * 911) ^ x;
|
||||
|
||||
return (hash_account ^ hash_currency ^ hash_issuer);
|
||||
}
|
||||
|
||||
STPathSet* STPathSet::construct (SerializerIterator& s, SField::ref name)
|
||||
{
|
||||
std::vector<STPath> paths;
|
||||
|
||||
@@ -192,29 +192,44 @@ public:
|
||||
// Combination of all types.
|
||||
};
|
||||
|
||||
private:
|
||||
static
|
||||
std::size_t
|
||||
get_hash (STPathElement const& element);
|
||||
|
||||
public:
|
||||
STPathElement (
|
||||
Account const& account, Currency const& currency,
|
||||
Account const& issuer, bool forceCurrency = false)
|
||||
: mAccountID (account), mCurrencyID (currency), mIssuerID (issuer)
|
||||
: mType (typeNone), mAccountID (account), mCurrencyID (currency)
|
||||
, mIssuerID (issuer), is_offer_ (isXRP(mAccountID))
|
||||
{
|
||||
mType =
|
||||
(account.isZero () ? 0 : STPathElement::typeAccount)
|
||||
| ((currency.isZero () && !forceCurrency) ? 0 :
|
||||
STPathElement::typeCurrency)
|
||||
| (issuer.isZero () ? 0 : STPathElement::typeIssuer);
|
||||
if (!is_offer_)
|
||||
mType |= typeAccount;
|
||||
|
||||
if (forceCurrency || !isXRP(currency))
|
||||
mType |= typeCurrency;
|
||||
|
||||
if (!isXRP(issuer))
|
||||
mType |= typeIssuer;
|
||||
|
||||
hash_value_ = get_hash (*this);
|
||||
}
|
||||
|
||||
STPathElement (
|
||||
unsigned int uType, Account const& account, Currency const& currency,
|
||||
Account const& issuer)
|
||||
: mType (uType), mAccountID (account), mCurrencyID (currency),
|
||||
mIssuerID (issuer)
|
||||
{}
|
||||
: mType (uType), mAccountID (account), mCurrencyID (currency)
|
||||
, mIssuerID (issuer), is_offer_ (isXRP(mAccountID))
|
||||
{
|
||||
hash_value_ = get_hash (*this);
|
||||
}
|
||||
|
||||
STPathElement ()
|
||||
: mType (0)
|
||||
{}
|
||||
: mType (typeNone), is_offer_ (true)
|
||||
{
|
||||
hash_value_ = get_hash (*this);
|
||||
}
|
||||
|
||||
int getNodeType () const
|
||||
{
|
||||
@@ -222,7 +237,7 @@ public:
|
||||
}
|
||||
bool isOffer () const
|
||||
{
|
||||
return mAccountID.isZero ();
|
||||
return is_offer_;
|
||||
}
|
||||
bool isAccount () const
|
||||
{
|
||||
@@ -246,10 +261,11 @@ public:
|
||||
|
||||
bool operator== (const STPathElement& t) const
|
||||
{
|
||||
return (mType & typeAccount) == (t.mType & typeAccount)
|
||||
&& mAccountID == t.mAccountID
|
||||
&& mCurrencyID == t.mCurrencyID
|
||||
&& mIssuerID == t.mIssuerID;
|
||||
return (mType & typeAccount) == (t.mType & typeAccount) &&
|
||||
hash_value_ == t.hash_value_ &&
|
||||
mAccountID == t.mAccountID &&
|
||||
mCurrencyID == t.mCurrencyID &&
|
||||
mIssuerID == t.mIssuerID;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -257,6 +273,9 @@ private:
|
||||
Account mAccountID;
|
||||
Currency mCurrencyID;
|
||||
Account mIssuerID;
|
||||
|
||||
bool is_offer_;
|
||||
std::size_t hash_value_;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user