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:
Edward Hennis
2017-09-21 19:05:50 -04:00
committed by Brad Chase
parent 0a48916d98
commit c11e186659
5 changed files with 38 additions and 9 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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())