Optimize audit_pool key hashing as well. Use a const for starting capacity for tx related lists.

This commit is contained in:
junderw 2023-06-24 23:42:18 -07:00 committed by Mononaut
parent ded2352cf8
commit 3c652bdcbc
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
2 changed files with 22 additions and 8 deletions

View File

@ -4,13 +4,18 @@ use std::{
collections::{HashMap, HashSet, VecDeque}, collections::{HashMap, HashSet, VecDeque},
}; };
use crate::{audit_transaction::AuditTransaction, GbtResult, ThreadTransactionsMap}; use crate::{
audit_transaction::AuditTransaction, utils::U32HasherState, GbtResult, ThreadTransactionsMap,
STARTING_CAPACITY,
};
const BLOCK_WEIGHT_UNITS: u32 = 4_000_000; const BLOCK_WEIGHT_UNITS: u32 = 4_000_000;
const BLOCK_SIGOPS: u32 = 80_000; const BLOCK_SIGOPS: u32 = 80_000;
const BLOCK_RESERVED_WEIGHT: u32 = 4_000; const BLOCK_RESERVED_WEIGHT: u32 = 4_000;
const MAX_BLOCKS: usize = 8; const MAX_BLOCKS: usize = 8;
type AuditPool = HashMap<u32, AuditTransaction, U32HasherState>;
struct TxPriority { struct TxPriority {
uid: u32, uid: u32,
score: f64, score: f64,
@ -42,8 +47,9 @@ impl Ord for TxPriority {
* Ported from https://github.com/mempool/mempool/blob/master/backend/src/api/tx-selection-worker.ts * Ported from https://github.com/mempool/mempool/blob/master/backend/src/api/tx-selection-worker.ts
*/ */
pub fn gbt(mempool: &mut ThreadTransactionsMap) -> Option<GbtResult> { pub fn gbt(mempool: &mut ThreadTransactionsMap) -> Option<GbtResult> {
let mut audit_pool: HashMap<u32, AuditTransaction> = HashMap::new(); let mut audit_pool: AuditPool =
let mut mempool_array: VecDeque<u32> = VecDeque::new(); HashMap::with_capacity_and_hasher(STARTING_CAPACITY, U32HasherState);
let mut mempool_array: VecDeque<u32> = VecDeque::with_capacity(STARTING_CAPACITY);
let mut clusters: Vec<Vec<u32>> = Vec::new(); let mut clusters: Vec<Vec<u32>> = Vec::new();
// Initialize working structs // Initialize working structs
@ -75,7 +81,7 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap) -> Option<GbtResult> {
let mut blocks: Vec<Vec<u32>> = Vec::new(); let mut blocks: Vec<Vec<u32>> = Vec::new();
let mut block_weight: u32 = BLOCK_RESERVED_WEIGHT; let mut block_weight: u32 = BLOCK_RESERVED_WEIGHT;
let mut block_sigops: u32 = 0; let mut block_sigops: u32 = 0;
let mut transactions: Vec<u32> = Vec::new(); let mut transactions: Vec<u32> = Vec::with_capacity(STARTING_CAPACITY);
let mut modified: PriorityQueue<u32, TxPriority> = PriorityQueue::new(); let mut modified: PriorityQueue<u32, TxPriority> = PriorityQueue::new();
let mut overflow: Vec<u32> = Vec::new(); let mut overflow: Vec<u32> = Vec::new();
let mut failures = 0; let mut failures = 0;
@ -167,7 +173,7 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap) -> Option<GbtResult> {
blocks.push(transactions); blocks.push(transactions);
} }
// reset for the next block // reset for the next block
transactions = Vec::new(); transactions = Vec::with_capacity(STARTING_CAPACITY);
block_weight = 4000; block_weight = 4000;
// 'overflow' packages didn't fit in this block, but are valid candidates for the next // 'overflow' packages didn't fit in this block, but are valid candidates for the next
overflow.reverse(); overflow.reverse();
@ -209,7 +215,7 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap) -> Option<GbtResult> {
}) })
} }
fn set_relatives(txid: u32, audit_pool: &mut HashMap<u32, AuditTransaction>) { fn set_relatives(txid: u32, audit_pool: &mut AuditPool) {
let mut parents: HashSet<u32> = HashSet::new(); let mut parents: HashSet<u32> = HashSet::new();
if let Some(tx) = audit_pool.get(&txid) { if let Some(tx) = audit_pool.get(&txid) {
if tx.relatives_set_flag { if tx.relatives_set_flag {
@ -267,7 +273,7 @@ fn set_relatives(txid: u32, audit_pool: &mut HashMap<u32, AuditTransaction>) {
// iterate over remaining descendants, removing the root as a valid ancestor & updating the ancestor score // iterate over remaining descendants, removing the root as a valid ancestor & updating the ancestor score
fn update_descendants( fn update_descendants(
root_txid: u32, root_txid: u32,
audit_pool: &mut HashMap<u32, AuditTransaction>, audit_pool: &mut AuditPool,
modified: &mut PriorityQueue<u32, TxPriority>, modified: &mut PriorityQueue<u32, TxPriority>,
cluster_rate: f64, cluster_rate: f64,
) { ) {

View File

@ -11,6 +11,14 @@ mod thread_transaction;
mod utils; mod utils;
use thread_transaction::ThreadTransaction; use thread_transaction::ThreadTransaction;
/// This is the starting capacity for HashMap/Vec/etc. that deal with transactions.
/// HashMap doubles capacity when it hits it, so 2048 is a decent tradeoff between
/// not wasting too much memory when it's below this, and allowing for less re-allocations
/// by virtue of starting with such a large capacity.
///
/// Note: This doesn't *have* to be a power of 2. (uwu)
const STARTING_CAPACITY: usize = 2048;
type ThreadTransactionsMap = HashMap<u32, ThreadTransaction, U32HasherState>; type ThreadTransactionsMap = HashMap<u32, ThreadTransaction, U32HasherState>;
#[napi] #[napi]
@ -25,7 +33,7 @@ impl GbtGenerator {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
thread_transactions: Arc::new(Mutex::new(HashMap::with_capacity_and_hasher( thread_transactions: Arc::new(Mutex::new(HashMap::with_capacity_and_hasher(
2048, STARTING_CAPACITY,
U32HasherState, U32HasherState,
))), ))),
} }