mirror of
https://github.com/monero-project/monero.git
synced 2024-12-25 11:19:26 -05:00
src: update internal data structure to boost::bimap.
startup speed up 2-5x because this PR changing O(n^2) operation to O(nlogn).
This commit is contained in:
parent
cc73fe7116
commit
445319d3f1
@ -29,6 +29,7 @@
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/bimap/support/iterator_type_by.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@ -42,6 +43,7 @@
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "int-util.h"
|
||||
#include "misc_language.h"
|
||||
#include "misc_log_ex.h"
|
||||
#include "warnings.h"
|
||||
#include "common/perf_timer.h"
|
||||
#include "crypto/hash.h"
|
||||
@ -464,7 +466,7 @@ namespace cryptonote
|
||||
break;
|
||||
try
|
||||
{
|
||||
const crypto::hash &txid = it->second;
|
||||
const crypto::hash &txid = it->get_right();
|
||||
txpool_tx_meta_t meta;
|
||||
if (!m_blockchain.get_txpool_tx_meta(txid, meta))
|
||||
{
|
||||
@ -491,11 +493,11 @@ namespace cryptonote
|
||||
return;
|
||||
}
|
||||
// remove first, in case this throws, so key images aren't removed
|
||||
MINFO("Pruning tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first);
|
||||
MINFO("Pruning tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->get_left().first);
|
||||
m_blockchain.remove_txpool_tx(txid);
|
||||
reduce_txpool_weight(meta.weight);
|
||||
remove_transaction_keyimages(tx, txid);
|
||||
MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first);
|
||||
MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->get_left().first);
|
||||
|
||||
auto it_prev = it;
|
||||
--it_prev;
|
||||
@ -751,13 +753,9 @@ namespace cryptonote
|
||||
m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();});
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
sorted_tx_container::iterator tx_memory_pool::find_tx_in_sorted_container(const crypto::hash& id) const
|
||||
sorted_tx_container::iterator tx_memory_pool::find_tx_in_sorted_container(const crypto::hash& id)
|
||||
{
|
||||
return std::find_if( m_txs_by_fee_and_receive_time.begin(), m_txs_by_fee_and_receive_time.end()
|
||||
, [&](const sorted_tx_container::value_type& a){
|
||||
return a.second == id;
|
||||
}
|
||||
);
|
||||
return m_txs_by_fee_and_receive_time.project_up(m_txs_by_fee_and_receive_time.right.find(id));
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
//TODO: investigate whether boolean return is appropriate
|
||||
@ -1644,15 +1642,15 @@ namespace cryptonote
|
||||
for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it)
|
||||
{
|
||||
txpool_tx_meta_t meta;
|
||||
if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta))
|
||||
if (!m_blockchain.get_txpool_tx_meta(sorted_it->get_right(), meta))
|
||||
{
|
||||
static bool warned = false;
|
||||
if (!warned)
|
||||
MERROR(" failed to find tx meta: " << sorted_it->second << " (will only print once)");
|
||||
MERROR(" failed to find tx meta: " << sorted_it->get_right() << " (will only print once)");
|
||||
warned = true;
|
||||
continue;
|
||||
}
|
||||
LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase) << ", relay method " << (unsigned)meta.get_relay_method());
|
||||
LOG_PRINT_L2("Considering " << sorted_it->get_right() << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase) << ", relay method " << (unsigned)meta.get_relay_method());
|
||||
|
||||
if (!meta.matches(relay_category::legacy) && !(m_mine_stem_txes && meta.get_relay_method() == relay_method::stem))
|
||||
{
|
||||
@ -1702,7 +1700,7 @@ namespace cryptonote
|
||||
}
|
||||
|
||||
// "local" and "stem" txes are filtered above
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second, relay_category::all);
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->get_right(), relay_category::all);
|
||||
|
||||
cryptonote::transaction tx;
|
||||
|
||||
@ -1713,7 +1711,7 @@ namespace cryptonote
|
||||
bool ready = false;
|
||||
try
|
||||
{
|
||||
ready = is_transaction_ready_to_go(meta, sorted_it->second, txblob, tx);
|
||||
ready = is_transaction_ready_to_go(meta, sorted_it->get_right(), txblob, tx);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@ -1724,7 +1722,7 @@ namespace cryptonote
|
||||
{
|
||||
try
|
||||
{
|
||||
m_blockchain.update_txpool_tx(sorted_it->second, meta);
|
||||
m_blockchain.update_txpool_tx(sorted_it->get_right(), meta);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@ -1743,7 +1741,7 @@ namespace cryptonote
|
||||
continue;
|
||||
}
|
||||
|
||||
bl.tx_hashes.push_back(sorted_it->second);
|
||||
bl.tx_hashes.push_back(sorted_it->get_right());
|
||||
total_weight += meta.weight;
|
||||
fee += meta.fee;
|
||||
best_coinbase = coinbase;
|
||||
@ -1854,7 +1852,11 @@ namespace cryptonote
|
||||
m_txs_by_fee_and_receive_time.erase(sorted_it);
|
||||
}
|
||||
}
|
||||
m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(fee, receive_time), txid);
|
||||
auto insert_result = m_txs_by_fee_and_receive_time.insert(sorted_tx_container::value_type(std::pair<double, time_t>(fee, receive_time), txid));
|
||||
|
||||
if (!insert_result.second) {
|
||||
MERROR("Failed to add txid " << txid << " to the m_txs_by_fee_and_receive_time");
|
||||
}
|
||||
|
||||
// Don't check for "resurrected" txs in case of reorgs i.e. don't check in 'm_removed_txs_by_time'
|
||||
// whether we have that txid there and if yes remove it; this results in possible duplicates
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include <queue>
|
||||
#include <boost/serialization/version.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/bimap.hpp>
|
||||
#include <boost/bimap/set_of.hpp>
|
||||
#include <boost/bimap/multiset_of.hpp>
|
||||
|
||||
#include "span.h"
|
||||
#include "string_tools.h"
|
||||
@ -62,24 +65,33 @@ namespace cryptonote
|
||||
//! pair of <transaction fee, transaction hash> for organization
|
||||
typedef std::pair<std::pair<double, std::time_t>, crypto::hash> tx_by_fee_and_receive_time_entry;
|
||||
|
||||
class txCompare
|
||||
class txFeeCompare
|
||||
{
|
||||
public:
|
||||
bool operator()(const tx_by_fee_and_receive_time_entry& a, const tx_by_fee_and_receive_time_entry& b) const
|
||||
bool operator()(const std::pair<double, std::time_t>& a, const std::pair<double, std::time_t>& b) const
|
||||
{
|
||||
// sort by greatest first, not least
|
||||
if (a.first.first > b.first.first) return true;
|
||||
if (a.first.first < b.first.first) return false;
|
||||
if (a.first > b.first) return true;
|
||||
if (a.first < b.first) return false;
|
||||
|
||||
if (a.first.second < b.first.second) return true;
|
||||
if (a.first.second > b.first.second) return false;
|
||||
if (a.second < b.second) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return memcmp(a.second.data, b.second.data, sizeof(crypto::hash)) < 0;
|
||||
class hashCompare
|
||||
{
|
||||
public:
|
||||
bool operator()(const crypto::hash& a, const crypto::hash& b) const
|
||||
{
|
||||
return memcmp(a.data, b.data, sizeof(crypto::hash)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//! container for sorting transactions by fee per unit size
|
||||
typedef std::set<tx_by_fee_and_receive_time_entry, txCompare> sorted_tx_container;
|
||||
typedef boost::bimap<boost::bimaps::multiset_of<std::pair<double, std::time_t>, txFeeCompare>,
|
||||
boost::bimaps::set_of<crypto::hash, hashCompare>> sorted_tx_container;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Transaction pool, handles transactions which are not part of a block
|
||||
@ -653,7 +665,7 @@ private:
|
||||
*
|
||||
* @return an iterator, possibly to the end of the container if not found
|
||||
*/
|
||||
sorted_tx_container::iterator find_tx_in_sorted_container(const crypto::hash& id) const;
|
||||
sorted_tx_container::iterator find_tx_in_sorted_container(const crypto::hash& id);
|
||||
|
||||
//! cache/call Blockchain::check_tx_inputs results
|
||||
bool check_tx_inputs(const std::function<cryptonote::transaction&(void)> &get_tx, const crypto::hash &txid, uint64_t &max_used_block_height, crypto::hash &max_used_block_id, tx_verification_context &tvc, bool kept_by_block = false) const;
|
||||
|
Loading…
Reference in New Issue
Block a user