mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 18:45:52 +00:00
Grow TxQ expected size quickly, shrink slowly (RIPD-1534):
* Stores recent history of "good" ledgers. Uses the maximum as the expected ledger size. When a large value drops off, use a 90% backoff to go down to to the new maximum. * If consensus is unhealthy, wipe the history in addition to the current clamping. * Include .md doc files in xcode and VS projects
This commit is contained in:
committed by
Brad Chase
parent
0a48916d98
commit
c11e186659
@@ -337,7 +337,7 @@ list(APPEND non_unity_srcs "${test_srcs}")
|
||||
|
||||
if(WIN32 OR is_xcode)
|
||||
# Rippled headers. Only needed for IDEs.
|
||||
file(GLOB_RECURSE rippled_headers src/*.h src/*.hpp)
|
||||
file(GLOB_RECURSE rippled_headers src/*.h src/*.hpp *.md)
|
||||
list(APPEND rippled_headers Builds/CMake/CMakeFuncs.cmake)
|
||||
foreach(curdir
|
||||
beast/asio
|
||||
|
||||
@@ -28,8 +28,12 @@ consensus process, but will be at least [5](#other-constants).
|
||||
* If consensus stays [healthy](#consensus-health), the limit will
|
||||
be the max of the current limit or the number of transactions in
|
||||
the validated ledger until it gets to [50](#other-constants), at
|
||||
which point, the limit will only be updated to the number of
|
||||
transactions in the validated ledger if it is larger than 50.
|
||||
which point, the limit will be the largest number of transactions
|
||||
in the last [20](#other-constants) validated ledgers which had
|
||||
more than 50 transactions. Any time the limit decreases (ie. a
|
||||
large ledger is no longer recent), the limit will decrease to the
|
||||
new largest value by 10% each time the ledger has more than 50
|
||||
transactions.
|
||||
* If consensus does not stay [healthy](#consensus-health),
|
||||
the limit will clamp down to the smaller of [50](#other-constants)
|
||||
or the number of transactions in the validated ledger.
|
||||
@@ -109,7 +113,8 @@ but in practice, either
|
||||
sequence number and at least a [25% higher fee](#other-constants), or
|
||||
* it will get dropped when the queue fills up with more valuable transactions.
|
||||
The size limit is computed dynamically, and can hold transactions for
|
||||
the next [20 ledgers](#other-constants). The lower the transaction's
|
||||
the next [20 ledgers](#other-constants) (restricted to a minimum of
|
||||
[2000 transactions](#other-constants)). The lower the transaction's
|
||||
fee, the more likely that it will get dropped if the network is busy.
|
||||
|
||||
If a transaction is submitted for an account with one or more transactions
|
||||
@@ -200,7 +205,9 @@ automatically as the ripple network's performance improves, allowing
|
||||
more transactions per second, and thus more transactions per ledger
|
||||
to process successfully. The limit of 20 ledgers was used to provide
|
||||
a balance between resource (specifically memory) usage, and giving
|
||||
transactions a realistic chance to be processed. This exact value was
|
||||
transactions a realistic chance to be processed. The minimum size of
|
||||
2000 transactions was chosen to allow a decent functional backlog during
|
||||
network congestion conditions. These exact values were
|
||||
chosen experimentally, and can easily change in the future.
|
||||
* *Maximum retries*. A transaction in the queue can attempt to apply
|
||||
to the open ledger, but get a retry (`ter`) code up to 10 times, at
|
||||
|
||||
@@ -1099,7 +1099,7 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
|
||||
}
|
||||
else if (e.result == terQUEUED)
|
||||
{
|
||||
JLOG(m_journal.info()) << "Transaction is likely to claim a " <<
|
||||
JLOG(m_journal.debug()) << "Transaction is likely to claim a " <<
|
||||
"fee, but is queued until fee drops";
|
||||
e.transaction->setStatus(HELD);
|
||||
// Add to held transactions, because it could get
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <ripple/protocol/TER.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -194,6 +195,9 @@ private:
|
||||
// One more than this value will be accepted
|
||||
// before escalation kicks in.
|
||||
std::size_t txnsExpected_;
|
||||
// Recent history of transaction counts that
|
||||
// exceed the targetTxnCount_
|
||||
boost::circular_buffer<std::size_t> recentTxnCounts_;
|
||||
// Minimum value of escalationMultiplier.
|
||||
std::uint64_t const minimumMultiplier_;
|
||||
// Based on the median fee of the LCL. Used
|
||||
@@ -213,6 +217,7 @@ private:
|
||||
targetTxnCount_ : *setup.maximumTxnInLedger :
|
||||
boost::optional<std::size_t>(boost::none))
|
||||
, txnsExpected_(minimumTxnCount_)
|
||||
, recentTxnCounts_(setup.ledgersInQueue)
|
||||
, minimumMultiplier_(setup.minimumEscalationMultiplier)
|
||||
, escalationMultiplier_(minimumMultiplier_)
|
||||
, j_(j)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <boost/algorithm/clamp.hpp>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -107,16 +108,32 @@ TxQ::FeeMetrics::update(Application& app,
|
||||
// so clamp down on limits.
|
||||
txnsExpected_ = boost::algorithm::clamp(feeLevels.size(),
|
||||
minimumTxnCount_, targetTxnCount_);
|
||||
recentTxnCounts_.clear();
|
||||
}
|
||||
else if (feeLevels.size() > txnsExpected_ ||
|
||||
feeLevels.size() > targetTxnCount_)
|
||||
{
|
||||
recentTxnCounts_.push_back(feeLevels.size());
|
||||
auto const iter = std::max_element(recentTxnCounts_.begin(),
|
||||
recentTxnCounts_.end());
|
||||
BOOST_ASSERT(iter != recentTxnCounts_.end());
|
||||
auto const next = [&]
|
||||
{
|
||||
// Grow quickly: If the max_element is >= the
|
||||
// current size limit, use it.
|
||||
if (*iter >= txnsExpected_)
|
||||
return *iter;
|
||||
// Shrink slowly: If the max_element is < the
|
||||
// current size limit, use a limit that is
|
||||
// 90% of the way from max_element to the
|
||||
// current size limit.
|
||||
return (txnsExpected_ * 9 + *iter) / 10;
|
||||
}();
|
||||
// Ledgers are processing in a timely manner,
|
||||
// so keep the limit high, but don't let it
|
||||
// grow without bound.
|
||||
txnsExpected_ = maximumTxnCount_ ?
|
||||
std::min(feeLevels.size(), *maximumTxnCount_) :
|
||||
feeLevels.size();
|
||||
txnsExpected_ = std::min(next,
|
||||
maximumTxnCount_.value_or(next));
|
||||
}
|
||||
|
||||
if (feeLevels.empty())
|
||||
|
||||
Reference in New Issue
Block a user