computer: perf again

This commit is contained in:
nym21
2025-07-13 00:21:20 +02:00
parent 1e71e2d68f
commit 85f6ef063d
3 changed files with 234 additions and 180 deletions

View File

@@ -9,7 +9,7 @@ use super::ByAddressType;
pub struct AddressTypeToTypeIndexTree<T>(ByAddressType<BTreeMap<TypeIndex, T>>);
impl<T> AddressTypeToTypeIndexTree<T> {
pub fn merge(&mut self, mut other: Self) {
pub fn merge(mut self, mut other: Self) -> Self {
Self::merge_(&mut self.p2pk65, &mut other.p2pk65);
Self::merge_(&mut self.p2pk33, &mut other.p2pk33);
Self::merge_(&mut self.p2pkh, &mut other.p2pkh);
@@ -18,6 +18,7 @@ impl<T> AddressTypeToTypeIndexTree<T> {
Self::merge_(&mut self.p2wsh, &mut other.p2wsh);
Self::merge_(&mut self.p2tr, &mut other.p2tr);
Self::merge_(&mut self.p2a, &mut other.p2a);
self
}
fn merge_(own: &mut BTreeMap<TypeIndex, T>, other: &mut BTreeMap<TypeIndex, T>) {

View File

@@ -2,5 +2,20 @@ use derive_deref::{Deref, DerefMut};
use super::ByAddressType;
#[derive(Debug, Default, Deref, DerefMut)]
#[derive(Debug, Deref, DerefMut)]
pub struct AddressTypeToVec<T>(ByAddressType<Vec<T>>);
impl<T> Default for AddressTypeToVec<T> {
fn default() -> Self {
Self(ByAddressType {
p2pk65: vec![],
p2pk33: vec![],
p2pkh: vec![],
p2sh: vec![],
p2wpkh: vec![],
p2wsh: vec![],
p2tr: vec![],
p2a: vec![],
})
}
}

View File

@@ -24,7 +24,7 @@ use crate::{
addresstype_to_addresscount::AddressTypeToAddressCount,
addresstype_to_height_to_addresscount::AddressTypeToHeightToAddressCount,
addresstype_to_indexes_to_addresscount::AddressTypeToIndexesToAddressCount,
r#trait::DynCohortVecs,
addresstype_to_typeindex_set::AddressTypeToTypeIndexSet, r#trait::DynCohortVecs,
},
},
};
@@ -40,6 +40,7 @@ mod address_cohorts;
mod addresstype_to_addresscount;
mod addresstype_to_height_to_addresscount;
mod addresstype_to_indexes_to_addresscount;
mod addresstype_to_typeindex_set;
mod addresstype_to_typeindex_tree;
mod addresstype_to_vec;
mod common;
@@ -758,6 +759,7 @@ impl Vecs {
addresstype_to_typedindex_to_received_data,
mut height_to_sent,
addresstype_to_typedindex_to_sent_data,
mut stored_addressindexes,
) = thread::scope(|scope| {
scope.spawn(|| {
self.utxo_vecs.tick_tock_next_block(&chain_state, timestamp);
@@ -766,10 +768,10 @@ impl Vecs {
let received = scope.spawn(|| {
let mut transacted = Transacted::default();
let mut addresstype_to_typedindex_to_received_data = AddressTypeToVec::<
(TypeIndex, Sats, Option<WithAddressDataSource<AddressData>>),
>::default(
);
let mut addresstype_to_typedindex_to_received_data =
AddressTypeToVec::<(TypeIndex, Sats)>::default();
let mut receiving_addressindexes = AddressTypeToTypeIndexSet::default();
let _ = (first_outputindex..first_outputindex + *output_count)
.map(OutputIndex::from)
@@ -789,61 +791,32 @@ impl Vecs {
let typeindex = outputindex_to_typeindex
.unwrap_read(outputindex, &outputindex_to_typeindex_mmap);
let addressdata_opt = if *first_addressindexes
.get(output_type)
receiving_addressindexes
.get_mut(output_type)
.unwrap()
<= typeindex
{
Some(WithAddressDataSource::New(AddressData::default()))
} else if !addresstype_to_typeindex_to_addressdata
.get(output_type)
.unwrap()
.contains_key(&typeindex)
&& !addresstype_to_typeindex_to_emptyaddressdata
.get(output_type)
.unwrap()
.contains_key(&typeindex)
{
Some(
if let Some(addressdata) = stores
.get_addressdata(output_type, typeindex)
.unwrap()
{
WithAddressDataSource::FromAddressDataStore(
addressdata,
)
} else if let Some(emptyaddressdata) = stores
.get_emptyaddressdata(output_type, typeindex)
.unwrap()
{
WithAddressDataSource::FromEmptyAddressDataStore(
emptyaddressdata.into(),
)
} else {
unreachable!("I think ?")
},
)
} else {
None
};
.insert(typeindex);
addresstype_to_typedindex_to_received_data
.get_mut(output_type)
.unwrap()
.push((typeindex, value, addressdata_opt));
.push((typeindex, value));
ControlFlow::Continue(())
});
(transacted, addresstype_to_typedindex_to_received_data)
(
transacted,
addresstype_to_typedindex_to_received_data,
receiving_addressindexes,
)
});
let mut height_to_sent = BTreeMap::<Height, Transacted>::default();
let mut addresstype_to_typedindex_to_sent_data = HeightToAddressTypeToVec::<
(TypeIndex, Sats, Option<WithAddressDataSource<AddressData>>),
>::default(
);
let mut addresstype_to_typedindex_to_sent_data =
HeightToAddressTypeToVec::<(TypeIndex, Sats)>::default();
let mut sending_addressindexes = AddressTypeToTypeIndexSet::default();
// Skip coinbase
let _ = (first_inputindex + 1..first_inputindex + *input_count)
@@ -873,44 +846,93 @@ impl Vecs {
let typeindex = outputindex_to_typeindex
.unwrap_read(outputindex, &outputindex_to_typeindex_mmap);
let addressdata_opt = if *first_addressindexes
.get(input_type)
sending_addressindexes
.get_mut(input_type)
.unwrap()
> typeindex
&& !addresstype_to_typeindex_to_addressdata
.get(input_type)
.unwrap()
.contains_key(&typeindex)
&& let Some(address_data) =
stores.get_addressdata(input_type, typeindex).unwrap()
// Otherwise it was empty and got funds in the same block before sending them
{
Some(WithAddressDataSource::FromAddressDataStore(address_data))
} else {
None
};
.insert(typeindex);
addresstype_to_typedindex_to_sent_data
.entry(prev_height)
.or_default()
.get_mut(input_type)
.unwrap()
.push((typeindex, value, addressdata_opt));
.push((typeindex, value));
ControlFlow::Continue(())
});
let (transacted, addresstype_to_typedindex_to_received_data) =
received.join().unwrap();
let (
transacted,
addresstype_to_typedindex_to_received_data,
receiving_addressindexes,
) = received.join().unwrap();
let stored_addressindexes =
sending_addressindexes.merge(receiving_addressindexes);
(
transacted,
addresstype_to_typedindex_to_received_data,
height_to_sent,
addresstype_to_typedindex_to_sent_data,
stored_addressindexes,
)
});
let mut stored_addressdata_with_source = stored_addressindexes
.into_typed_vec()
.into_par_iter()
.flat_map(|(_type, set)| {
set.into_par_iter().map(move |index| (_type, index))
})
.flat_map(|(_type, index)| {
if *first_addressindexes.get(_type).unwrap() <= index {
Some((
_type,
index,
WithAddressDataSource::New(AddressData::default()),
))
} else if addresstype_to_typeindex_to_addressdata
.get(_type)
.unwrap()
.contains_key(&index)
|| addresstype_to_typeindex_to_emptyaddressdata
.get(_type)
.unwrap()
.contains_key(&index)
{
None
} else if let Some(addressdata) =
stores.get_addressdata(_type, index).unwrap()
{
Some((
_type,
index,
WithAddressDataSource::FromAddressDataStore(addressdata),
))
} else if let Some(emptyaddressdata) =
stores.get_emptyaddressdata(_type, index).unwrap()
{
Some((
_type,
index,
WithAddressDataSource::FromEmptyAddressDataStore(
emptyaddressdata.into(),
),
))
} else {
unreachable!()
}
})
.fold(
AddressTypeToTypeIndexTree::default,
|mut tree, (_type, index, addressdata)| {
tree.get_mut(_type).unwrap().insert(index, addressdata);
tree
},
)
.reduce(AddressTypeToTypeIndexTree::default, |a, b| a.merge(b));
thread::scope(|scope| {
scope.spawn(|| {
addresstype_to_typedindex_to_received_data.process_received(
@@ -920,6 +942,7 @@ impl Vecs {
price,
&mut addresstype_to_address_count,
&mut addresstype_to_empty_address_count,
&mut stored_addressdata_with_source,
);
addresstype_to_typedindex_to_sent_data
@@ -934,6 +957,7 @@ impl Vecs {
&height_to_timestamp_fixed_vec,
height,
timestamp,
&mut stored_addressdata_with_source,
)
.unwrap();
});
@@ -1332,7 +1356,8 @@ impl Vecs {
}
}
impl AddressTypeToVec<(TypeIndex, Sats, Option<WithAddressDataSource<AddressData>>)> {
impl AddressTypeToVec<(TypeIndex, Sats)> {
#[allow(clippy::too_many_arguments)]
fn process_received(
mut self,
vecs: &mut address_cohorts::Vecs,
@@ -1345,76 +1370,82 @@ impl AddressTypeToVec<(TypeIndex, Sats, Option<WithAddressDataSource<AddressData
price: Option<Dollars>,
addresstype_to_address_count: &mut ByAddressType<usize>,
addresstype_to_empty_address_count: &mut ByAddressType<usize>,
stored_addressdata_with_source: &mut AddressTypeToTypeIndexTree<
WithAddressDataSource<AddressData>,
>,
) {
self.into_typed_vec().into_iter().for_each(|(_type, vec)| {
vec.into_iter()
.for_each(|(type_index, value, addressdata_opt)| {
let mut is_new = false;
let mut from_any_empty = false;
vec.into_iter().for_each(|(type_index, value)| {
let mut is_new = false;
let mut from_any_empty = false;
let addressdata_withsource = addresstype_to_typeindex_to_addressdata
.get_mut(_type)
.unwrap()
.entry(type_index)
.or_insert_with(|| {
addresstype_to_typeindex_to_emptyaddressdata
.get_mut(_type)
.unwrap()
.remove(&type_index)
.map(|ad| {
from_any_empty = true;
ad.into()
})
.unwrap_or_else(|| {
let addressdata = addressdata_opt.unwrap();
is_new = addressdata.is_new();
from_any_empty = addressdata.is_from_emptyaddressdata();
addressdata
})
});
let addressdata_withsource = addresstype_to_typeindex_to_addressdata
.get_mut(_type)
.unwrap()
.entry(type_index)
.or_insert_with(|| {
addresstype_to_typeindex_to_emptyaddressdata
.get_mut(_type)
.unwrap()
.remove(&type_index)
.map(|ad| {
from_any_empty = true;
ad.into()
})
.unwrap_or_else(|| {
let addressdata = stored_addressdata_with_source
.get_mut(_type)
.unwrap()
.remove(&type_index)
.unwrap();
is_new = addressdata.is_new();
from_any_empty = addressdata.is_from_emptyaddressdata();
addressdata
})
});
if is_new || from_any_empty {
(*addresstype_to_address_count.get_mut(_type).unwrap()) += 1;
if from_any_empty {
(*addresstype_to_empty_address_count.get_mut(_type).unwrap()) -= 1;
}
if is_new || from_any_empty {
(*addresstype_to_address_count.get_mut(_type).unwrap()) += 1;
if from_any_empty {
(*addresstype_to_empty_address_count.get_mut(_type).unwrap()) -= 1;
}
}
let addressdata = addressdata_withsource.deref_mut();
let prev_amount = addressdata.amount();
let amount = prev_amount + value;
if is_new
|| from_any_empty
|| vecs.amount_range.get_mut(amount).0.clone()
!= vecs.amount_range.get_mut(prev_amount).0.clone()
{
// dbg!((prev_amount, amount, is_new));
if !is_new && !from_any_empty {
let state = &mut vecs.amount_range.get_mut(prev_amount).1.state;
// dbg!((prev_amount, &state.address_count, &addressdata));
state.subtract(addressdata);
}
let addressdata = addressdata_withsource.deref_mut();
addressdata.receive(value, price);
let prev_amount = addressdata.amount();
let amount = prev_amount + value;
if is_new
|| from_any_empty
|| vecs.amount_range.get_mut(amount).0.clone()
!= vecs.amount_range.get_mut(prev_amount).0.clone()
{
// dbg!((prev_amount, amount, is_new));
if !is_new && !from_any_empty {
let state = &mut vecs.amount_range.get_mut(prev_amount).1.state;
// dbg!((prev_amount, &state.address_count, &addressdata));
state.subtract(addressdata);
}
addressdata.receive(value, price);
vecs.amount_range.get_mut(amount).1.state.add(addressdata);
} else {
vecs.amount_range.get_mut(amount).1.state.receive(
addressdata,
value,
price,
);
}
});
vecs.amount_range.get_mut(amount).1.state.add(addressdata);
} else {
vecs.amount_range
.get_mut(amount)
.1
.state
.receive(addressdata, value, price);
}
});
});
}
}
impl HeightToAddressTypeToVec<(TypeIndex, Sats, Option<WithAddressDataSource<AddressData>>)> {
impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
#[allow(clippy::too_many_arguments)]
fn process_sent(
self,
@@ -1432,6 +1463,9 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats, Option<WithAddressDataSource<Add
height_to_timestamp_fixed_vec: &[Timestamp],
height: Height,
timestamp: Timestamp,
stored_addressdata_with_source: &mut AddressTypeToTypeIndexTree<
WithAddressDataSource<AddressData>,
>,
) -> Result<()> {
self.0.into_iter().try_for_each(|(prev_height, mut v)| {
let prev_price = height_to_close_vec
@@ -1452,70 +1486,74 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats, Option<WithAddressDataSource<Add
.is_more_than_hour();
v.into_typed_vec().into_iter().try_for_each(|(_type, vec)| {
vec.into_iter()
.try_for_each(|(type_index, value, addressdata_opt)| {
let typeindex_to_addressdata = addresstype_to_typeindex_to_addressdata
.get_mut(_type)
.unwrap();
vec.into_iter().try_for_each(|(type_index, value)| {
let typeindex_to_addressdata = addresstype_to_typeindex_to_addressdata
.get_mut(_type)
.unwrap();
let addressdata_withsource = typeindex_to_addressdata
.entry(type_index)
.or_insert_with(|| addressdata_opt.unwrap());
let addressdata_withsource = typeindex_to_addressdata
.entry(type_index)
.or_insert_with(|| {
stored_addressdata_with_source
.get_mut(_type)
.unwrap()
.remove(&type_index)
.unwrap()
});
let addressdata = addressdata_withsource.deref_mut();
let addressdata = addressdata_withsource.deref_mut();
let prev_amount = addressdata.amount();
let prev_amount = addressdata.amount();
let amount = prev_amount.checked_sub(value).unwrap();
let amount = prev_amount.checked_sub(value).unwrap();
let will_be_empty = addressdata.outputs_len - 1 == 0;
let will_be_empty = addressdata.outputs_len - 1 == 0;
// dbg!((prev_amount, amount, will_be_empty));
// dbg!((prev_amount, amount, will_be_empty));
if will_be_empty
|| vecs.amount_range.get_mut(amount).0.clone()
!= vecs.amount_range.get_mut(prev_amount).0.clone()
{
vecs.amount_range
.get_mut(prev_amount)
.1
.state
.subtract(addressdata);
if will_be_empty
|| vecs.amount_range.get_mut(amount).0.clone()
!= vecs.amount_range.get_mut(prev_amount).0.clone()
{
vecs.amount_range
.get_mut(prev_amount)
.1
.state
.subtract(addressdata);
addressdata.send(value, prev_price)?;
addressdata.send(value, prev_price)?;
if will_be_empty {
if amount.is_not_zero() {
unreachable!()
}
(*addresstype_to_address_count.get_mut(_type).unwrap()) -= 1;
(*addresstype_to_empty_address_count.get_mut(_type).unwrap()) += 1;
let addressdata =
typeindex_to_addressdata.remove(&type_index).unwrap();
addresstype_to_typeindex_to_emptyaddressdata
.get_mut(_type)
.unwrap()
.insert(type_index, addressdata.into());
} else {
vecs.amount_range.get_mut(amount).1.state.add(addressdata);
if will_be_empty {
if amount.is_not_zero() {
unreachable!()
}
} else {
vecs.amount_range.get_mut(amount).1.state.send(
addressdata,
value,
price,
prev_price,
blocks_old,
days_old,
older_than_hour,
)?;
}
Ok(())
})
(*addresstype_to_address_count.get_mut(_type).unwrap()) -= 1;
(*addresstype_to_empty_address_count.get_mut(_type).unwrap()) += 1;
let addressdata = typeindex_to_addressdata.remove(&type_index).unwrap();
addresstype_to_typeindex_to_emptyaddressdata
.get_mut(_type)
.unwrap()
.insert(type_index, addressdata.into());
} else {
vecs.amount_range.get_mut(amount).1.state.add(addressdata);
}
} else {
vecs.amount_range.get_mut(amount).1.state.send(
addressdata,
value,
price,
prev_price,
blocks_old,
days_old,
older_than_hour,
)?;
}
Ok(())
})
})
})
}