Compare commits

...

1 Commits

Author SHA1 Message Date
Mayukha Vadari
b197ae92f2 perf: Remove SHAMap overhead on hot paths
- SHAMapNodeID derived from CountedObject, so every construction,
  copy and destruction updated one process-wide atomic counter. Tree
  walks create one per level, so all threads contended on that counter.
  The count was only used for get_counts diagnostics.
- NodePathStack used std::stack's default std::deque, which allocates
  on first push. Use a small_vector with 16 inline entries instead.
- fetchNodeNT canonicalized a node that fetchNodeFromDB had already
  canonicalized, which took the TreeNodeCache lock a second time.
2026-10-14 12:27:20 -04:00
3 changed files with 7 additions and 8 deletions

View File

@@ -17,6 +17,8 @@
#include <xrpl/shamap/SHAMapNodeID.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <boost/container/small_vector.hpp>
#include <condition_variable>
#include <cstddef>
#include <cstdint>
@@ -518,7 +520,9 @@ private:
}
private:
std::stack<std::pair<SHAMapTreeNodePtr, SHAMapNodeID>> stack_;
// Paths are rarely deeper than 16 nodes, so the inline buffer avoids the heap.
using Entry = std::pair<SHAMapTreeNodePtr, SHAMapNodeID>;
std::stack<Entry, boost::container::small_vector<Entry, 16>> stack_;
};
using DeltaRef =

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/CountedObject.h>
#include <xrpl/basics/base_uint.h>
#include <compare>
@@ -16,7 +15,7 @@ namespace xrpl {
/**
* Identifies a node inside a SHAMap
*/
class SHAMapNodeID : public CountedObject<SHAMapNodeID>
class SHAMapNodeID
{
private:
UInt256 id_;
@@ -98,8 +97,6 @@ public:
*
* Only a *defaulted* operator<=> implicitly declares a defaulted
* operator==; the one above is user-provided, so == has to be written.
* It cannot be defaulted either, because a defaulted == would also compare
* the CountedObject base, which is not equality comparable.
*/
bool
operator==(SHAMapNodeID const& n) const

View File

@@ -244,12 +244,10 @@ SHAMap::fetchNodeNT(SHAMapHash const& hash, SHAMapSyncFilter const* filter) cons
if (backed_)
{
// fetchNodeFromDB has already canonicalized the node.
node = fetchNodeFromDB(hash);
if (node)
{
canonicalize(hash, node);
return node;
}
}
if (filter != nullptr)