mirror of
https://github.com/monero-project/monero.git
synced 2024-12-26 11:49:22 -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
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <boost/bimap/support/iterator_type_by.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -42,6 +43,7 @@
|
|||||||
#include "blockchain_db/blockchain_db.h"
|
#include "blockchain_db/blockchain_db.h"
|
||||||
#include "int-util.h"
|
#include "int-util.h"
|
||||||
#include "misc_language.h"
|
#include "misc_language.h"
|
||||||
|
#include "misc_log_ex.h"
|
||||||
#include "warnings.h"
|
#include "warnings.h"
|
||||||
#include "common/perf_timer.h"
|
#include "common/perf_timer.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
@ -464,7 +466,7 @@ namespace cryptonote
|
|||||||
break;
|
break;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const crypto::hash &txid = it->second;
|
const crypto::hash &txid = it->get_right();
|
||||||
txpool_tx_meta_t meta;
|
txpool_tx_meta_t meta;
|
||||||
if (!m_blockchain.get_txpool_tx_meta(txid, meta))
|
if (!m_blockchain.get_txpool_tx_meta(txid, meta))
|
||||||
{
|
{
|
||||||
@ -491,11 +493,11 @@ namespace cryptonote
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// remove first, in case this throws, so key images aren't removed
|
// 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);
|
m_blockchain.remove_txpool_tx(txid);
|
||||||
reduce_txpool_weight(meta.weight);
|
reduce_txpool_weight(meta.weight);
|
||||||
remove_transaction_keyimages(tx, txid);
|
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;
|
auto it_prev = it;
|
||||||
--it_prev;
|
--it_prev;
|
||||||
@ -751,13 +753,9 @@ namespace cryptonote
|
|||||||
m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();});
|
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()
|
return m_txs_by_fee_and_receive_time.project_up(m_txs_by_fee_and_receive_time.right.find(id));
|
||||||
, [&](const sorted_tx_container::value_type& a){
|
|
||||||
return a.second == id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
//TODO: investigate whether boolean return is appropriate
|
//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)
|
for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it)
|
||||||
{
|
{
|
||||||
txpool_tx_meta_t meta;
|
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;
|
static bool warned = false;
|
||||||
if (!warned)
|
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;
|
warned = true;
|
||||||
continue;
|
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))
|
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
|
// "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;
|
cryptonote::transaction tx;
|
||||||
|
|
||||||
@ -1713,7 +1711,7 @@ namespace cryptonote
|
|||||||
bool ready = false;
|
bool ready = false;
|
||||||
try
|
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)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
@ -1724,7 +1722,7 @@ namespace cryptonote
|
|||||||
{
|
{
|
||||||
try
|
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)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
@ -1743,7 +1741,7 @@ namespace cryptonote
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bl.tx_hashes.push_back(sorted_it->second);
|
bl.tx_hashes.push_back(sorted_it->get_right());
|
||||||
total_weight += meta.weight;
|
total_weight += meta.weight;
|
||||||
fee += meta.fee;
|
fee += meta.fee;
|
||||||
best_coinbase = coinbase;
|
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.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'
|
// 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
|
// whether we have that txid there and if yes remove it; this results in possible duplicates
|
||||||
|
@ -39,6 +39,9 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <boost/serialization/version.hpp>
|
#include <boost/serialization/version.hpp>
|
||||||
#include <boost/utility.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 "span.h"
|
||||||
#include "string_tools.h"
|
#include "string_tools.h"
|
||||||
@ -62,24 +65,33 @@ namespace cryptonote
|
|||||||
//! pair of <transaction fee, transaction hash> for organization
|
//! 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;
|
typedef std::pair<std::pair<double, std::time_t>, crypto::hash> tx_by_fee_and_receive_time_entry;
|
||||||
|
|
||||||
class txCompare
|
class txFeeCompare
|
||||||
{
|
{
|
||||||
public:
|
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
|
// sort by greatest first, not least
|
||||||
if (a.first.first > b.first.first) return true;
|
if (a.first > b.first) return true;
|
||||||
if (a.first.first < b.first.first) return false;
|
if (a.first < b.first) return false;
|
||||||
|
|
||||||
if (a.first.second < b.first.second) return true;
|
if (a.second < b.second) return true;
|
||||||
if (a.first.second > b.first.second) return false;
|
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
|
//! 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
|
* @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
|
* @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
|
//! 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;
|
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