Optimize pending transactions filter (#9026)

* rpc: return unordered transactions in pending transactions filter

* ethcore: use LruCache for nonce cache

Only clear the nonce cache when a block is retracted

* Revert "ethcore: use LruCache for nonce cache"

This reverts commit b382c19abdb9985be1724c3b8cde83906da07d68.

* Use only cached nonces when computing pending hashes.

* Give filters their own locks, so that they don't block one another.

* Fix pending transaction count if not sealing.

* Clear cache only when block is enacted.

* Fix RPC tests.

* Address review comments.
This commit is contained in:
Tomasz Drwięga
2018-07-04 17:37:55 +02:00
committed by André Silva
parent 9438afde32
commit 08332f1945
10 changed files with 232 additions and 118 deletions

View File

@@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::time::{Instant, Duration};
use std::collections::{BTreeMap, HashSet, HashMap};
use std::collections::{BTreeMap, BTreeSet, HashSet, HashMap};
use std::sync::Arc;
use ansi_term::Colour;
@@ -838,7 +838,40 @@ impl miner::MinerService for Miner {
self.transaction_queue.all_transactions()
}
fn ready_transactions<C>(&self, chain: &C) -> Vec<Arc<VerifiedTransaction>> where
fn pending_transaction_hashes<C>(&self, chain: &C) -> BTreeSet<H256> where
C: ChainInfo + Sync,
{
let chain_info = chain.chain_info();
let from_queue = || self.transaction_queue.pending_hashes(
|sender| self.nonce_cache.read().get(sender).cloned(),
);
let from_pending = || {
self.map_existing_pending_block(|sealing| {
sealing.transactions()
.iter()
.map(|signed| signed.hash())
.collect()
}, chain_info.best_block_number)
};
match self.options.pending_set {
PendingSet::AlwaysQueue => {
from_queue()
},
PendingSet::AlwaysSealing => {
from_pending().unwrap_or_default()
},
PendingSet::SealingOrElseQueue => {
from_pending().unwrap_or_else(from_queue)
},
}
}
fn ready_transactions<C>(&self, chain: &C)
-> Vec<Arc<VerifiedTransaction>>
where
C: ChainInfo + Nonce + Sync,
{
let chain_info = chain.chain_info();
@@ -1043,8 +1076,12 @@ impl miner::MinerService for Miner {
// 2. We ignore blocks that are `invalid` because it doesn't have any meaning in terms of the transactions that
// are in those blocks
// Clear nonce cache
self.nonce_cache.write().clear();
let has_new_best_block = enacted.len() > 0;
if has_new_best_block {
// Clear nonce cache
self.nonce_cache.write().clear();
}
// First update gas limit in transaction queue and minimal gas price.
let gas_limit = *chain.best_block_header().gas_limit();
@@ -1069,10 +1106,12 @@ impl miner::MinerService for Miner {
});
}
// ...and at the end remove the old ones
self.transaction_queue.cull(client);
if has_new_best_block {
// ...and at the end remove the old ones
self.transaction_queue.cull(client);
}
if enacted.len() > 0 || (imported.len() > 0 && self.options.reseal_on_uncle) {
if has_new_best_block || (imported.len() > 0 && self.options.reseal_on_uncle) {
// Reset `next_allowed_reseal` in case a block is imported.
// Even if min_period is high, we will always attempt to create
// new pending block.

View File

@@ -28,7 +28,7 @@ pub mod stratum;
pub use self::miner::{Miner, MinerOptions, Penalization, PendingSet, AuthoringParams};
use std::sync::Arc;
use std::collections::BTreeMap;
use std::collections::{BTreeSet, BTreeMap};
use bytes::Bytes;
use ethereum_types::{H256, U256, Address};
@@ -164,7 +164,13 @@ pub trait MinerService : Send + Sync {
fn next_nonce<C>(&self, chain: &C, address: &Address) -> U256
where C: Nonce + Sync;
/// Get a list of all ready transactions.
/// Get a set of all pending transaction hashes.
///
/// Depending on the settings may look in transaction pool or only in pending block.
fn pending_transaction_hashes<C>(&self, chain: &C) -> BTreeSet<H256> where
C: ChainInfo + Sync;
/// Get a list of all ready transactions either ordered by priority or unordered (cheaper).
///
/// Depending on the settings may look in transaction pool or only in pending block.
fn ready_transactions<C>(&self, chain: &C) -> Vec<Arc<VerifiedTransaction>>