Reserve correct vector size for fee calculations:

* Using txnsExpected_, which is influenced by both the config
  and network behavior, can reserve far too much or far too
  little memory, wasting time and resources.
* Not an issue during normal operation, but a user could
  cause problems on their local node with extreme configuration
  settings.
This commit is contained in:
Edward Hennis
2018-11-28 18:50:02 -05:00
committed by Nik Bougalis
parent 259fb1c32e
commit 2432f13903
2 changed files with 40 additions and 8 deletions

View File

@@ -83,15 +83,20 @@ TxQ::FeeMetrics::update(Application& app,
TxQ::Setup const& setup) TxQ::Setup const& setup)
{ {
std::vector<uint64_t> feeLevels; std::vector<uint64_t> feeLevels;
feeLevels.reserve(txnsExpected_); auto const txBegin = view.txs.begin();
for (auto const& tx : view.txs) auto const txEnd = view.txs.end();
{ auto const size = std::distance(txBegin, txEnd);
auto const baseFee = calculateBaseFee(view, *tx.first); feeLevels.reserve(size);
feeLevels.push_back(getFeeLevelPaid(*tx.first, std::for_each(txBegin, txEnd,
baseLevel, baseFee, setup)); [&](auto const& tx)
} {
auto const baseFee = calculateBaseFee(view, *tx.first);
feeLevels.push_back(getFeeLevelPaid(*tx.first,
baseLevel, baseFee, setup));
}
);
std::sort(feeLevels.begin(), feeLevels.end()); std::sort(feeLevels.begin(), feeLevels.end());
auto const size = feeLevels.size(); assert(size == feeLevels.size());
JLOG(j_.debug()) << "Ledger " << view.info().seq << JLOG(j_.debug()) << "Ledger " << view.info().seq <<
" has " << size << " transactions. " << " has " << size << " transactions. " <<

View File

@@ -198,6 +198,32 @@ struct Regression_test : public beast::unit_test::suite
} }
} }
void testFeeEscalationExtremeConfig()
{
testcase("Fee escalation shouldn't allocate extreme memory");
using clock_type = std::chrono::steady_clock;
using namespace jtx;
using namespace std::chrono_literals;
Env env(*this, envconfig([](std::unique_ptr<Config> cfg)
{
auto& s = cfg->section("transaction_queue");
s.set("minimum_txn_in_ledger_standalone", "4294967295");
s.set("minimum_txn_in_ledger", "4294967295");
s.set("target_txn_in_ledger", "4294967295");
s.set("normal_consensus_increase_percent", "4294967295");
return cfg;
}));
env(noop(env.master));
// This test will probably fail if any breakpoints are encountered,
// but should pass on even the slowest machines.
auto const start = clock_type::now();
env.close();
BEAST_EXPECT(clock_type::now() - start < 1s);
}
void testJsonInvalid() void testJsonInvalid()
{ {
using namespace jtx; using namespace jtx;
@@ -221,6 +247,7 @@ struct Regression_test : public beast::unit_test::suite
testLowBalanceDestroy(); testLowBalanceDestroy();
testSecp256r1key(); testSecp256r1key();
testFeeEscalationAutofill(); testFeeEscalationAutofill();
testFeeEscalationExtremeConfig();
testJsonInvalid(); testJsonInvalid();
} }
}; };