Skip to content

Commit 6344965

Browse files
committed
tx_memory_pool: speedup get_complement() for large requests
Changes complexity from M*N to (2*N+M)*log2(M). The FCMP++ stressnet recently hit mempool sizes of ~55k txs. If the requesting node's mempool is populated, this results in an average of (55000*55000)/2 (about 1.5 billion) comparisons for the responding node. Under this commit, this would be reduced to (55000+55000)*log2(55000) comparisons (about 2.6 million), a 99.83% reduction.
1 parent 6bb3630 commit 6344965

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

src/cryptonote_core/tx_pool.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -671,12 +671,27 @@ namespace cryptonote
671671
CRITICAL_REGION_LOCAL(m_transactions_lock);
672672
CRITICAL_REGION_LOCAL1(m_blockchain);
673673

674-
m_blockchain.for_all_txpool_txes([this, &hashes, &txes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref*) {
674+
// Create an ordering for `crypto::hash` and sort `hashes` according to that order
675+
struct hash_compare
676+
{
677+
bool operator()(const crypto::hash &lhs, const crypto::hash &rhs) const noexcept
678+
{
679+
return memcmp(lhs.data, rhs.data, sizeof(crypto::hash)) < 0;
680+
}
681+
};
682+
std::vector<crypto::hash> hashes_sorted(hashes.cbegin(), hashes.cend());
683+
std::sort(hashes_sorted.begin(), hashes_sorted.end(), hash_compare{});
684+
685+
m_blockchain.for_all_txpool_txes([this, &hashes_sorted, &txes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref*) {
675686
const auto tx_relay_method = meta.get_relay_method();
676687
if (tx_relay_method != relay_method::block && tx_relay_method != relay_method::fluff)
677688
return true;
678-
const auto i = std::find(hashes.begin(), hashes.end(), txid);
679-
if (i == hashes.end())
689+
690+
// Do binary search for our pool TXID in given list, skip to next if already present
691+
const auto hash_it = std::lower_bound(hashes_sorted.cbegin(), hashes_sorted.cend(), txid, hash_compare{});
692+
if (hash_it != hashes_sorted.cend() && *hash_it == txid)
693+
return true;
694+
680695
{
681696
cryptonote::blobdata bd;
682697
try

0 commit comments

Comments
 (0)