mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-22 14:50:54 +00:00
Two suspects from the 3.3.0 slowdown investigation had no signal. Both were already computing the numbers and throwing them away, so this exposes them rather than adding measurement. Per-sweep heap trim. The trim runs after every cache sweep, and its cost scales with resident heap, so it is the leading explanation for a node with a populated database syncing slower than a fresh one. The report already carried duration, fault deltas and reclaimed pages, but the whole measurement sat behind a debug-journal check, so an ordinary node measured nothing, and the call site discarded the result. The measurement now always runs and only the log line stays gated. Records trim duration, minor faults and reclaimed kilobytes. Measured cost of the always-on path is about six microseconds per sweep against a trim costing milliseconds, at a cadence of ten to a hundred and twenty seconds. Honest limit, stated in the runbook: the fault delta spans only the trim call, so it shows the trim itself faulting but not the faults that follow as caches refill. The duration is the signal to correlate against sweep-job queueing. Rotation writes. Rotation copies archive-served reads forward and re-stores nodes missing from both backends, both of which compete with sync I/O and only happen on a populated online_delete database. The copy-forward count existed but was reset by the rotation's own log line, so a metric reading it would drop to zero on every swap; a never-reset total sits beside it now. The re-store count was not measured at all. Rotation duration is deliberately not recorded: the health throttle sleeps at eight points inside the sequence and dominates exactly when the node is unhealthy, so the number would conflate work with waiting. Nothing added for the other two suspects. Get-object serving is already covered by the handler label, the lookup histogram and the deferred and saturation gauges; peer churn by the disconnect-reason counter. Also replaces nine per-file cspell ignores with one ignoreRegExpList entry for the telemetry macro names, and picks up the levelization baseline for the consensus span-name test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
93 lines
3.1 KiB
C++
93 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include <xrpl/beast/utility/Journal.h>
|
|
#include <xrpl/nodestore/Backend.h>
|
|
#include <xrpl/nodestore/Database.h>
|
|
#include <xrpl/nodestore/Scheduler.h>
|
|
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
namespace xrpl::NodeStore {
|
|
|
|
/* This class has two key-value store Backend objects for persisting SHAMap
|
|
* records. This facilitates online deletion of data. New backends are
|
|
* rotated in. Old ones are rotated out and deleted.
|
|
*/
|
|
|
|
class DatabaseRotating : public Database
|
|
{
|
|
public:
|
|
DatabaseRotating(
|
|
Scheduler& scheduler,
|
|
int readThreads,
|
|
Section const& config,
|
|
beast::Journal journal)
|
|
: Database(scheduler, readThreads, config, journal)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Rotates the backends.
|
|
*
|
|
* @param newBackend New writable backend
|
|
* @param f A function executed after the rotation outside of lock. The
|
|
* values passed to f will be the new backend database names _after_
|
|
* rotation.
|
|
*/
|
|
virtual void
|
|
rotate(
|
|
std::unique_ptr<NodeStore::Backend>&& newBackend,
|
|
std::function<void(std::string const& writableName, std::string const& archiveName)> const&
|
|
f) = 0;
|
|
|
|
/**
|
|
* Marks an online-delete rotation as in progress (or completed).
|
|
*
|
|
* While in flight, a read served by the archive backend is copied
|
|
* forward into the writable backend even for ordinary
|
|
* (duplicate == false) fetches: the archive is about to be deleted,
|
|
* and a node body canonicalized into caches during the rotation
|
|
* window would otherwise survive only in RAM once the archive is
|
|
* dropped.
|
|
*/
|
|
virtual void
|
|
setRotationInFlight(bool inFlight) = 0;
|
|
|
|
/**
|
|
* Whether an online-delete rotation is in progress right now.
|
|
*
|
|
* A rotation's extra writes only happen inside this window, so a panel
|
|
* reading the copy-forward total needs this to know when to expect it to
|
|
* move. Outside the window a flat total is correct, not a broken signal.
|
|
*
|
|
* @return true between the cache-freshen phase starting and rotate()
|
|
* completing.
|
|
*/
|
|
[[nodiscard]] virtual bool
|
|
isRotationInFlight() const = 0;
|
|
|
|
/**
|
|
* Nodes copied forward from the archive backend into the writable one
|
|
* during rotation windows, since this process started.
|
|
*
|
|
* These are writes an ordinary fetch would not have performed: the archive
|
|
* is about to be deleted, so a body it served has to be rewritten to
|
|
* survive. The count therefore scales with how much of the archive is read
|
|
* during a rotation, which is why it appears only on a populated,
|
|
* already-rotated online_delete database.
|
|
*
|
|
* Cumulative for the lifetime of the process, deliberately: the per-rotation
|
|
* tally that `rotate()` logs is reset on every swap, and a counter that goes
|
|
* backwards cannot be rated. A panel takes the rate of this instead.
|
|
*
|
|
* @return Monotonic count of copy-forward writes.
|
|
*/
|
|
[[nodiscard]] virtual std::uint64_t
|
|
copyForwardTotal() const = 0;
|
|
};
|
|
|
|
} // namespace xrpl::NodeStore
|