diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d648978bd1..76c75d17ed8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/src/ripple/app/misc/FeeEscalation.md b/src/ripple/app/misc/FeeEscalation.md index 211e6efcdff..6fb902e7948 100644 --- a/src/ripple/app/misc/FeeEscalation.md +++ b/src/ripple/app/misc/FeeEscalation.md @@ -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 diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index 1743034b118..765c27a0431 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -1099,7 +1099,7 @@ void NetworkOPsImp::apply (std::unique_lock& 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 diff --git a/src/ripple/app/misc/TxQ.h b/src/ripple/app/misc/TxQ.h index 27fc524a517..17e42aa35b1 100644 --- a/src/ripple/app/misc/TxQ.h +++ b/src/ripple/app/misc/TxQ.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace ripple { @@ -194,6 +195,9 @@ class TxQ // 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 recentTxnCounts_; // Minimum value of escalationMultiplier. std::uint64_t const minimumMultiplier_; // Based on the median fee of the LCL. Used @@ -213,6 +217,7 @@ class TxQ targetTxnCount_ : *setup.maximumTxnInLedger : boost::optional(boost::none)) , txnsExpected_(minimumTxnCount_) + , recentTxnCounts_(setup.ledgersInQueue) , minimumMultiplier_(setup.minimumEscalationMultiplier) , escalationMultiplier_(minimumMultiplier_) , j_(j) diff --git a/src/ripple/app/misc/impl/TxQ.cpp b/src/ripple/app/misc/impl/TxQ.cpp index 14d6766e900..b7fcd79ea90 100644 --- a/src/ripple/app/misc/impl/TxQ.cpp +++ b/src/ripple/app/misc/impl/TxQ.cpp @@ -29,6 +29,7 @@ #include #include #include +#include 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())