Compare commits

...

2 Commits

Author SHA1 Message Date
Valentin Balaschenko
5fc815703e more detailed tracing 2026-06-01 11:57:19 +01:00
Valentin Balaschenko
a4abf883cf logs for ref counts 2026-05-31 18:04:34 +01:00
2 changed files with 51 additions and 2 deletions

View File

@@ -7,6 +7,24 @@
namespace xrpl {
namespace detail {
// All-time peak strong/weak ref counts ever observed across all
// IntrusiveRefCounts instances. Read from doSweep periodically.
inline std::atomic<std::uint32_t> kPeakStrongObserved{0};
inline std::atomic<std::uint32_t> kPeakWeakObserved{0};
inline void
updateRefCountPeak(std::atomic<std::uint32_t>& peak, std::uint32_t v) noexcept
{
auto cur = peak.load(std::memory_order_relaxed);
while (v > cur && !peak.compare_exchange_weak(
cur, v, std::memory_order_relaxed))
{
// retry; cur is updated by compare_exchange_weak on failure
}
}
} // namespace detail
/** Action to perform when releasing a strong pointer.
noop: Do nothing. For example, a `noop` action will occur when a count is
@@ -226,13 +244,18 @@ private:
inline void
IntrusiveRefCounts::addStrongRef() const noexcept
{
refCounts_.fetch_add(kStrongDelta, std::memory_order_acq_rel);
auto const prev = refCounts_.fetch_add(kStrongDelta, std::memory_order_acq_rel);
auto const newStrong = static_cast<std::uint32_t>((prev & kStrongMask) + 1);
detail::updateRefCountPeak(detail::kPeakStrongObserved, newStrong);
}
inline void
IntrusiveRefCounts::addWeakRef() const noexcept
{
refCounts_.fetch_add(kWeakDelta, std::memory_order_acq_rel);
auto const prev = refCounts_.fetch_add(kWeakDelta, std::memory_order_acq_rel);
auto const newWeak =
static_cast<std::uint32_t>(((prev & kWeakMask) >> kStrongCountNumBits) + 1);
detail::updateRefCountPeak(detail::kPeakWeakObserved, newWeak);
}
inline ReleaseStrongRefAction
@@ -331,6 +354,11 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
(!(prevIntVal & kPartialDestroyStartedMask)),
"xrpl::IntrusiveRefCounts::addWeakReleaseStrongRef : not "
"started partial destroy");
// This op converts one strong into one weak: capture the new
// weak count for the leak-proof peak.
auto const newWeak = static_cast<std::uint32_t>(
((prevIntVal & kWeakMask) >> kStrongCountNumBits) + 1);
detail::updateRefCountPeak(detail::kPeakWeakObserved, newWeak);
return action;
}
}
@@ -377,6 +405,10 @@ IntrusiveRefCounts::checkoutStrongRefFromWeak() const noexcept
desiredValue = curValue + kStrongDelta;
}
// Successful CAS promoted a weak ref to strong. Capture the new strong
// count for the leak-proof peak.
auto const newStrong = static_cast<std::uint32_t>(desiredValue & kStrongMask);
detail::updateRefCountPeak(detail::kPeakStrongObserved, newStrong);
return true;
}
@@ -413,6 +445,8 @@ inline IntrusiveRefCounts::RefCountPair::RefCountPair(IntrusiveRefCounts::FieldT
, partialDestroyStartedBit{v & kPartialDestroyStartedMask}
, partialDestroyFinishedBit{v & kPartialDestroyFinishedMask}
{
detail::updateRefCountPeak(detail::kPeakStrongObserved, strong);
detail::updateRefCountPeak(detail::kPeakWeakObserved, weak);
XRPL_ASSERT(
(strong < kCheckStrongMaxValue && weak < kCheckWeakMaxValue),
"xrpl::IntrusiveRefCounts::RefCountPair(FieldType) : inputs inside "

View File

@@ -1084,6 +1084,21 @@ public:
<< "; size after: " << cachedSLEs_.size();
}
{
auto const peakStrong =
xrpl::detail::kPeakStrongObserved.load(std::memory_order_relaxed);
auto const peakWeak =
xrpl::detail::kPeakWeakObserved.load(std::memory_order_relaxed);
constexpr std::uint32_t kStrongLimit = 65503; // kCheckStrongMaxValue
constexpr std::uint32_t kWeakLimit = 16351; // kCheckWeakMaxValue
JLOG(journal_.warn())
<< "RefCount peak since startup: "
<< "strong=" << peakStrong << "/" << kStrongLimit
<< " (" << (peakStrong * 100 / kStrongLimit) << "%); "
<< "weak=" << peakWeak << "/" << kWeakLimit
<< " (" << (peakWeak * 100 / kWeakLimit) << "%)";
}
mallocTrim("doSweep", journal_);
// Set timer to do another sweep later.