diff --git a/.gitignore b/.gitignore index 8e8834d1e..5a9bc1631 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,8 @@ _* # Logs .log + +# Profiling +profile.json.gz +flamegraph.svg +*.trace diff --git a/crates/brk/.gitignore b/crates/brk/.gitignore deleted file mode 100644 index 996e0ebda..000000000 --- a/crates/brk/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -profile.json.gz -flamegraph.svg diff --git a/crates/brk_computer/examples/main.rs b/crates/brk_computer/examples/main.rs index 9de2efeb3..6b921befa 100644 --- a/crates/brk_computer/examples/main.rs +++ b/crates/brk_computer/examples/main.rs @@ -13,7 +13,8 @@ pub fn main() -> color_eyre::Result<()> { brk_logger::init(Some(Path::new(".log"))); - let bitcoin_dir = default_bitcoin_path(); + // let bitcoin_dir = default_bitcoin_path(); + let bitcoin_dir = Path::new("/Volumes/WD_BLACK/bitcoin"); let rpc = Box::leak(Box::new(bitcoincore_rpc::Client::new( "http://localhost:8332", @@ -23,11 +24,11 @@ pub fn main() -> color_eyre::Result<()> { // Can't increase main thread's stack programatically, thus we need to use another thread thread::Builder::new() - .stack_size(32 * 1024 * 1024) + .stack_size(256 * 1024 * 1024) .spawn(move || -> color_eyre::Result<()> { let parser = Parser::new(bitcoin_dir.join("blocks"), rpc); - let _outputs_dir = default_brk_path().join("outputs"); + let _outputs_dir = Path::new("/Volumes/WD_BLACK/brk").join("outputs"); let outputs_dir = _outputs_dir.as_path(); // let outputs_dir = Path::new("../../_outputs"); diff --git a/crates/brk_computer/flamegraph.sh b/crates/brk_computer/flamegraph.sh new file mode 100755 index 000000000..23a23b08b --- /dev/null +++ b/crates/brk_computer/flamegraph.sh @@ -0,0 +1,2 @@ +cargo build --profile profiling +flamegraph -- ../../target/profiling/examples/main diff --git a/crates/brk_computer/samply.sh b/crates/brk_computer/samply.sh new file mode 100755 index 000000000..d32802d12 --- /dev/null +++ b/crates/brk_computer/samply.sh @@ -0,0 +1,2 @@ +cargo build --example main --profile profiling +samply record ../../target/profiling/examples/main diff --git a/crates/brk_computer/src/vecs/stateful/addresstype_to_vec.rs b/crates/brk_computer/src/vecs/stateful/addresstype_to_vec.rs index 73a4ee48b..8e65398be 100644 --- a/crates/brk_computer/src/vecs/stateful/addresstype_to_vec.rs +++ b/crates/brk_computer/src/vecs/stateful/addresstype_to_vec.rs @@ -1,30 +1,6 @@ -use std::mem; - use derive_deref::{Deref, DerefMut}; use super::ByAddressType; #[derive(Debug, Default, Deref, DerefMut)] pub struct AddressTypeToVec(ByAddressType>); - -impl AddressTypeToVec { - pub fn merge(&mut self, mut other: 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); - Self::merge_(&mut self.p2sh, &mut other.p2sh); - Self::merge_(&mut self.p2wpkh, &mut other.p2wpkh); - Self::merge_(&mut self.p2wsh, &mut other.p2wsh); - Self::merge_(&mut self.p2tr, &mut other.p2tr); - Self::merge_(&mut self.p2a, &mut other.p2a); - } - - fn merge_(own: &mut Vec, other: &mut Vec) { - if own.len() >= other.len() { - own.append(other); - } else { - other.append(own); - mem::swap(own, other); - } - } -} diff --git a/crates/brk_computer/src/vecs/stateful/mod.rs b/crates/brk_computer/src/vecs/stateful/mod.rs index d173014ed..5c055f84b 100644 --- a/crates/brk_computer/src/vecs/stateful/mod.rs +++ b/crates/brk_computer/src/vecs/stateful/mod.rs @@ -1,4 +1,4 @@ -use std::{cmp::Ordering, collections::BTreeMap, mem, path::Path, thread}; +use std::{cmp::Ordering, collections::BTreeMap, mem, ops::ControlFlow, path::Path, thread}; use brk_core::{ AddressData, ByAddressType, CheckedSub, DateIndex, Dollars, EmptyAddressData, Height, @@ -8,7 +8,7 @@ use brk_exit::Exit; use brk_indexer::Indexer; use brk_vec::{ AnyCollectableVec, AnyVec, CollectableVec, Computation, EagerVec, Format, GenericStoredVec, - StoredIndex, StoredVec, UnsafeSlice, VecIterator, + StoredIndex, StoredVec, VecIterator, }; use either::Either; use log::info; @@ -57,7 +57,7 @@ use range_map::*; use r#trait::CohortVecs; pub use withaddressdatasource::WithAddressDataSource; -const VERSION: Version = Version::new(12); +const VERSION: Version = Version::new(18); #[derive(Clone)] pub struct Vecs { @@ -497,11 +497,11 @@ impl Vecs { let dateindex_to_first_height = &indexes.dateindex_to_first_height; let dateindex_to_height_count = &indexes.dateindex_to_height_count; - let inputindex_to_outputindex_mmap = inputindex_to_outputindex.mmap().load(); let outputindex_to_value_mmap = outputindex_to_value.mmap().load(); let outputindex_to_outputtype_mmap = outputindex_to_outputtype.mmap().load(); let outputindex_to_typeindex_mmap = outputindex_to_typeindex.mmap().load(); + let mut inputindex_to_outputindex_iter = inputindex_to_outputindex.into_iter(); let mut height_to_first_outputindex_iter = height_to_first_outputindex.into_iter(); let mut height_to_first_inputindex_iter = height_to_first_inputindex.into_iter(); let mut height_to_first_p2aaddressindex_iter = height_to_first_p2aaddressindex.into_iter(); @@ -701,6 +701,8 @@ impl Vecs { .try_for_each(|_height| -> color_eyre::Result<()> { height = _height; + info!("Processing chain at {height}..."); + self.utxo_vecs .as_mut_separate_vecs() .iter_mut() @@ -711,8 +713,6 @@ impl Vecs { .iter_mut() .for_each(|(_, v)| v.state.reset_single_iteration_values()); - info!("Processing chain at {height}..."); - let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height); let price = height_to_close_iter .as_mut() @@ -754,357 +754,229 @@ impl Vecs { }; let ( - (mut height_to_sent, addresstype_to_typedindex_to_sent_data), - (mut transacted, addresstype_to_typedindex_to_received_data), - ) = thread::scope(|s| { - if chain_state_starting_height <= height { - s.spawn(|| { - self.utxo_vecs.tick_tock_next_block(&chain_state, timestamp); - }); - } - - let sent_handle = s.spawn(|| { - // Skip coinbase - (first_inputindex + 1..first_inputindex + *input_count) - .into_par_iter() - .map(InputIndex::from) - .map(|inputindex| { - let outputindex = inputindex_to_outputindex - .get_or_read( - inputindex, - &inputindex_to_outputindex_mmap, - ) - .unwrap() - .unwrap() - .into_owned(); - - let value = outputindex_to_value - .get_or_read(outputindex, &outputindex_to_value_mmap) - .unwrap() - .unwrap() - .into_owned(); - - let input_type = outputindex_to_outputtype - .get_or_read( - outputindex, - &outputindex_to_outputtype_mmap, - ) - .unwrap() - .unwrap() - .into_owned(); - - let prev_height = - *outputindex_range_to_height.get(outputindex).unwrap(); - - if input_type.is_unspendable() { - unreachable!() - } else if input_type.is_not_address() { - return ( - prev_height, - value, - input_type, - None, - ); - } - - let typeindex = outputindex_to_typeindex - .get_or_read( - outputindex, - &outputindex_to_typeindex_mmap, - ) - .unwrap() - .unwrap() - .into_owned(); - - let addressdata_opt = if input_type.is_address() - && *first_addressindexes.get(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 - }; - - ( - prev_height, - value, - input_type, - Some((typeindex, addressdata_opt)), - ) - }) - .fold( - || { - ( - BTreeMap::::default(), - HeightToAddressTypeToVec::<( - TypeIndex, - Sats, - Option>, - )>::default( - ), - ) - }, - |(mut tree, mut tree2), - ( - height, - value, - input_type, - address_data_opt, - )| { - tree.entry(height) - .or_default() - .iterate(value, input_type); - if let Some((typeindex, addressdata_opt)) = - address_data_opt - { - tree2 - .entry(height) - .or_default() - .get_mut(input_type) - .unwrap() - .push((typeindex, value, addressdata_opt)); - } - (tree, tree2) - }, - ) - .reduce( - || { - ( - BTreeMap::::default(), - HeightToAddressTypeToVec::<( - TypeIndex, - Sats, - Option>, - )>::default( - ), - ) - }, - |(first_tree, first_tree2), (second_tree, second_tree2)| { - let (mut tree_source, tree_to_consume) = - if first_tree.len() > second_tree.len() { - (first_tree, second_tree) - } else { - (second_tree, first_tree) - }; - tree_to_consume.into_iter().for_each(|(k, v)| { - *tree_source.entry(k).or_default() += v; - }); - - let (mut tree_source2, tree_to_consume2) = - if first_tree2.len() > second_tree2.len() { - (first_tree2, second_tree2) - } else { - (second_tree2, first_tree2) - }; - tree_to_consume2.0.into_iter().for_each(|(k, v)| { - tree_source2.entry(k).or_default().merge(v); - }); - - (tree_source, tree_source2) - }, - ) + mut transacted, + addresstype_to_typedindex_to_received_data, + mut height_to_sent, + addresstype_to_typedindex_to_sent_data, + ) = thread::scope(|scope| { + scope.spawn(|| { + self.utxo_vecs.tick_tock_next_block(&chain_state, timestamp); }); - let received_output = (first_outputindex - ..first_outputindex + *output_count) - .into_par_iter() - .map(OutputIndex::from) - .map(|outputindex| { - let value = outputindex_to_value - .get_or_read(outputindex, &outputindex_to_value_mmap) - .unwrap() - .unwrap() - .into_owned(); + let received = scope.spawn(|| { + let mut transacted = Transacted::default(); - let output_type = outputindex_to_outputtype - .get_or_read(outputindex, &outputindex_to_outputtype_mmap) - .unwrap() - .unwrap() - .into_owned(); + let mut addresstype_to_typedindex_to_received_data = AddressTypeToVec::< + (TypeIndex, Sats, Option>), + >::default( + ); - if output_type.is_not_address() { - return (value, output_type, None); - } + let _ = (first_outputindex..first_outputindex + *output_count) + .map(OutputIndex::from) + .try_for_each(|outputindex| -> ControlFlow<()> { + let value = outputindex_to_value + .unwrap_read(outputindex, &outputindex_to_value_mmap); - let typeindex = outputindex_to_typeindex - .get_or_read(outputindex, &outputindex_to_typeindex_mmap) - .unwrap() - .unwrap() - .into_owned(); + let output_type = outputindex_to_outputtype + .unwrap_read(outputindex, &outputindex_to_outputtype_mmap); - let addressdata_opt = if *first_addressindexes - .get(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 + transacted.iterate(value, output_type); + + if output_type.is_not_address() { + return ControlFlow::Continue(()); + } + + let typeindex = outputindex_to_typeindex + .unwrap_read(outputindex, &outputindex_to_typeindex_mmap); + + let addressdata_opt = if *first_addressindexes + .get(output_type) + .unwrap() + <= typeindex + { + Some(WithAddressDataSource::New(AddressData::default())) + } else if !addresstype_to_typeindex_to_addressdata .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) + && !addresstype_to_typeindex_to_emptyaddressdata + .get(output_type) .unwrap() - { - WithAddressDataSource::FromEmptyAddressDataStore( - emptyaddressdata.into(), - ) - } else { - WithAddressDataSource::New(AddressData::default()) - }, - ) + .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 + }; + + addresstype_to_typedindex_to_received_data + .get_mut(output_type) + .unwrap() + .push((typeindex, value, addressdata_opt)); + + ControlFlow::Continue(()) + }); + + (transacted, addresstype_to_typedindex_to_received_data) + }); + + let mut height_to_sent = BTreeMap::::default(); + + let mut addresstype_to_typedindex_to_sent_data = HeightToAddressTypeToVec::< + (TypeIndex, Sats, Option>), + >::default( + ); + + // Skip coinbase + let _ = (first_inputindex + 1..first_inputindex + *input_count) + .map(InputIndex::from) + .try_for_each(|inputindex| -> ControlFlow<()> { + let outputindex = + inputindex_to_outputindex_iter.unwrap_get_inner(inputindex); + + let value = outputindex_to_value + .unwrap_read(outputindex, &outputindex_to_value_mmap); + + let input_type = outputindex_to_outputtype + .unwrap_read(outputindex, &outputindex_to_outputtype_mmap); + + let prev_height = + *outputindex_range_to_height.get(outputindex).unwrap(); + + height_to_sent + .entry(prev_height) + .or_default() + .iterate(value, input_type); + + if input_type.is_not_address() { + return ControlFlow::Continue(()); + } + + let typeindex = outputindex_to_typeindex + .unwrap_read(outputindex, &outputindex_to_typeindex_mmap); + + let addressdata_opt = if *first_addressindexes + .get(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 }; - ( - value, - output_type, - Some((typeindex, addressdata_opt)), - ) - }) - .fold( - || { - ( - Transacted::default(), - AddressTypeToVec::<( - TypeIndex, - Sats, - Option>, - )>::default(), - ) - }, - |(mut transacted, mut vecs), - ( - value, - output_type, - typeindex_with_addressdata_opt, - )| { - transacted.iterate(value, output_type); - if let Some(vec) = vecs.get_mut(output_type) { - let (typeindex, addressdata_opt) = - typeindex_with_addressdata_opt.unwrap(); - vec.push((typeindex, value, addressdata_opt)); - } + addresstype_to_typedindex_to_sent_data + .entry(prev_height) + .or_default() + .get_mut(input_type) + .unwrap() + .push((typeindex, value, addressdata_opt)); - (transacted, vecs) - }, - ) - .reduce( - || { - ( - Transacted::default(), - AddressTypeToVec::<( - TypeIndex, - Sats, - Option>, - )>::default(), - ) - }, - |(transacted, mut vecs), (other_transacted, other_vecs)| { - vecs.merge(other_vecs); + ControlFlow::Continue(()) + }); - (transacted + other_transacted, vecs) - }, - ); + let (transacted, addresstype_to_typedindex_to_received_data) = + received.join().unwrap(); - (sent_handle.join().unwrap(), received_output) + ( + transacted, + addresstype_to_typedindex_to_received_data, + height_to_sent, + addresstype_to_typedindex_to_sent_data, + ) }); - if chain_state_starting_height > height { - dbg!(chain_state_starting_height, height); - panic!("temp, just making sure") - } - - unspendable_supply += transacted - .by_type - .unspendable - .as_vec() - .into_iter() - .map(|state| state.value) - .sum::() - + height_to_unclaimed_rewards_iter.unwrap_get_inner(height); - - opreturn_supply += transacted.by_type.unspendable.opreturn.value; - - if height == Height::new(0) { - transacted = Transacted::default(); - unspendable_supply += Sats::FIFTY_BTC; - } else if height == Height::new(91_842) || height == Height::new(91_880) { - // Need to destroy invalid coinbases due to duplicate txids - if height == Height::new(91_842) { - height_to_sent.entry(Height::new(91_812)).or_default() - } else { - height_to_sent.entry(Height::new(91_722)).or_default() - } - .iterate(Sats::FIFTY_BTC, OutputType::P2PK65); - }; - - thread::scope(|scope| -> Result<()> { + thread::scope(|scope| { scope.spawn(|| { - // Push current block state before processing sends and receives - chain_state.push(BlockState { - supply: transacted.spendable_supply.clone(), + addresstype_to_typedindex_to_received_data.process_received( + &mut self.address_vecs, + &mut addresstype_to_typeindex_to_addressdata, + &mut addresstype_to_typeindex_to_emptyaddressdata, price, - timestamp, - }); + &mut addresstype_to_address_count, + &mut addresstype_to_empty_address_count, + ); - self.utxo_vecs.receive(transacted, height, price); - - let unsafe_chain_state = UnsafeSlice::new(&mut chain_state); - - height_to_sent.par_iter().for_each(|(height, sent)| unsafe { - (*unsafe_chain_state.get(height.unwrap_to_usize())).supply -= - &sent.spendable_supply; - }); - - self.utxo_vecs.send(height_to_sent, chain_state.as_slice()); + addresstype_to_typedindex_to_sent_data + .process_sent( + &mut self.address_vecs, + &mut addresstype_to_typeindex_to_addressdata, + &mut addresstype_to_typeindex_to_emptyaddressdata, + price, + &mut addresstype_to_address_count, + &mut addresstype_to_empty_address_count, + height_to_close_vec.as_ref(), + &height_to_timestamp_fixed_vec, + height, + timestamp, + ) + .unwrap(); }); - addresstype_to_typedindex_to_received_data.process_received( - &mut self.address_vecs, - &mut addresstype_to_typeindex_to_addressdata, - &mut addresstype_to_typeindex_to_emptyaddressdata, - price, - &mut addresstype_to_address_count, - &mut addresstype_to_empty_address_count, - ); + if chain_state_starting_height > height { + dbg!(chain_state_starting_height, height); + panic!("temp, just making sure") + } - addresstype_to_typedindex_to_sent_data.process_sent( - &mut self.address_vecs, - &mut addresstype_to_typeindex_to_addressdata, - &mut addresstype_to_typeindex_to_emptyaddressdata, + unspendable_supply += transacted + .by_type + .unspendable + .as_vec() + .into_iter() + .map(|state| state.value) + .sum::() + + height_to_unclaimed_rewards_iter.unwrap_get_inner(height); + + opreturn_supply += transacted.by_type.unspendable.opreturn.value; + + if height == Height::new(0) { + transacted = Transacted::default(); + unspendable_supply += Sats::FIFTY_BTC; + } else if height == Height::new(91_842) || height == Height::new(91_880) { + // Need to destroy invalid coinbases due to duplicate txids + if height == Height::new(91_842) { + height_to_sent.entry(Height::new(91_812)).or_default() + } else { + height_to_sent.entry(Height::new(91_722)).or_default() + } + .iterate(Sats::FIFTY_BTC, OutputType::P2PK65); + }; + // Push current block state before processing sends and receives + chain_state.push(BlockState { + supply: transacted.spendable_supply.clone(), price, - &mut addresstype_to_address_count, - &mut addresstype_to_empty_address_count, - height_to_close_vec.as_ref(), - &height_to_timestamp_fixed_vec, - height, timestamp, - )?; + }); - Ok(()) - })?; + self.utxo_vecs.receive(transacted, height, price); + + self.utxo_vecs.send(height_to_sent, &mut chain_state); + }); let mut separate_utxo_vecs = self.utxo_vecs.as_mut_separate_vecs(); @@ -1168,10 +1040,17 @@ impl Vecs { info!("Flushing..."); exit.block(); self.flush_states(height, &chain_state, exit)?; + + // Maybe keep some from the end for both + let addresstype_to_typeindex_to_addressdata_to_consume = + mem::take(&mut addresstype_to_typeindex_to_addressdata); + let addresstype_to_typeindex_to_emptyaddressdata_to_consume = + mem::take(&mut addresstype_to_typeindex_to_emptyaddressdata); + stores.commit( height, - mem::take(&mut addresstype_to_typeindex_to_addressdata), - mem::take(&mut addresstype_to_typeindex_to_emptyaddressdata), + addresstype_to_typeindex_to_addressdata_to_consume, + addresstype_to_typeindex_to_emptyaddressdata_to_consume, )?; exit.release(); } @@ -1565,7 +1444,7 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats, Option ControlFlow<()> { - let prev_days_old = block_state - .timestamp - .difference_in_days_between(prev_timestamp); - let days_old = block_state.timestamp.difference_in_days_between(timestamp); + let prev_days_old = + prev_timestamp.difference_in_days_between(block_state.timestamp); + let days_old = timestamp.difference_in_days_between(block_state.timestamp); if prev_days_old == days_old { return ControlFlow::Continue(()); @@ -1375,7 +1373,7 @@ impl Vecs { pub fn send( &mut self, height_to_sent: BTreeMap, - chain_state: &[BlockState], + chain_state: &mut [BlockState], ) { let mut time_based_vecs = self .0 @@ -1388,21 +1386,17 @@ impl Vecs { let last_timestamp = chain_state.last().unwrap().timestamp; let current_price = chain_state.last().unwrap().price; - // dbg!(&height_to_sent); - height_to_sent.into_iter().for_each(|(height, sent)| { + chain_state[height.unwrap_to_usize()].supply -= &sent.spendable_supply; + let block_state = chain_state.get(height.unwrap_to_usize()).unwrap(); let prev_price = block_state.price; let blocks_old = chain_state.len() - 1 - height.unwrap_to_usize(); - let days_old = block_state - .timestamp - .difference_in_days_between(last_timestamp); - - let days_old_float = block_state - .timestamp - .difference_in_days_between_float(last_timestamp); + let days_old = last_timestamp.difference_in_days_between(block_state.timestamp); + let days_old_float = + last_timestamp.difference_in_days_between_float(block_state.timestamp); let older_than_hour = last_timestamp .checked_sub(block_state.timestamp) diff --git a/crates/brk_core/src/structs/addressdata.rs b/crates/brk_core/src/structs/addressdata.rs index 00699f70f..c80148ee6 100644 --- a/crates/brk_core/src/structs/addressdata.rs +++ b/crates/brk_core/src/structs/addressdata.rs @@ -21,12 +21,12 @@ impl AddressData { (self.realized_cap / Bitcoin::from(self.amount())).round_to_4_digits() } - #[inline(always)] + #[inline] pub fn has_0_sats(&self) -> bool { self.amount() == Sats::ZERO } - #[inline(always)] + #[inline] pub fn has_0_utxos(&self) -> bool { self.outputs_len == 0 } diff --git a/crates/brk_core/src/structs/dollars.rs b/crates/brk_core/src/structs/dollars.rs index 3827be4bc..6b3a20d19 100644 --- a/crates/brk_core/src/structs/dollars.rs +++ b/crates/brk_core/src/structs/dollars.rs @@ -243,7 +243,7 @@ impl Mul for Dollars { self } else { Self::from(Cents::from( - u128::from(rhs) * u128::from(Cents::from(self)) / u128::from(Sats::ONE_BTC), + u128::from(rhs) * u128::from(Cents::from(self)) / Sats::ONE_BTC_U128, )) } } diff --git a/crates/brk_core/src/structs/sats.rs b/crates/brk_core/src/structs/sats.rs index 4905e592e..81c00d7ea 100644 --- a/crates/brk_core/src/structs/sats.rs +++ b/crates/brk_core/src/structs/sats.rs @@ -53,6 +53,7 @@ impl Sats { pub const ONE_BTC: Self = Self(1_00_000_000); pub const MAX: Self = Self(u64::MAX); pub const FIFTY_BTC: Self = Self(50_00_000_000); + pub const ONE_BTC_U128: u128 = 1_00_000_000; pub fn new(sats: u64) -> Self { Self(sats) diff --git a/crates/brk_core/src/structs/timestamp.rs b/crates/brk_core/src/structs/timestamp.rs index ea104574f..67d74dbd6 100644 --- a/crates/brk_core/src/structs/timestamp.rs +++ b/crates/brk_core/src/structs/timestamp.rs @@ -1,7 +1,4 @@ -use std::{ - cmp::Ordering, - ops::{Add, AddAssign, Div}, -}; +use std::ops::{Add, AddAssign, Div}; use derive_deref::Deref; use jiff::{civil::date, tz::TimeZone}; @@ -29,7 +26,9 @@ use super::Date; )] pub struct Timestamp(u32); -const ONE_DAY_IN_SEC: i64 = 24 * 60 * 60; +const ONE_HOUR_IN_SEC: u32 = 60 * 60; +const ONE_DAY_IN_SEC: u32 = 24 * 60 * 60; +const ONE_DAY_IN_SEC_F64: f64 = ONE_DAY_IN_SEC as f64; impl Timestamp { pub const ZERO: Self = Self(0); @@ -50,34 +49,25 @@ impl Timestamp { Self::from(trunc_date_time.to_zoned(TimeZone::UTC).unwrap().timestamp()) } - pub fn difference_in_days_between(&self, other: Self) -> usize { - match self.cmp(&other) { - Ordering::Equal => 0, - Ordering::Greater => other.difference_in_days_between(*self), - Ordering::Less => { - (jiff::Timestamp::from(*self) - .duration_until(jiff::Timestamp::from(other)) - .as_secs() - / ONE_DAY_IN_SEC) as usize - } - } + #[inline] + pub fn difference_in_days_between(&self, older: Self) -> usize { + // if self.0 < older.0 { + // unreachable!() + // } + ((self.0 - older.0) / ONE_DAY_IN_SEC) as usize } - pub fn difference_in_days_between_float(&self, other: Self) -> f64 { - match self.cmp(&other) { - Ordering::Equal => 0.0, - Ordering::Greater => other.difference_in_days_between_float(*self), - Ordering::Less => { - jiff::Timestamp::from(*self) - .duration_until(jiff::Timestamp::from(other)) - .as_secs() as f64 - / ONE_DAY_IN_SEC as f64 - } - } + #[inline] + pub fn difference_in_days_between_float(&self, older: Self) -> f64 { + // if self.0 < older.0 { + // unreachable!() + // } + (self.0 - older.0) as f64 / ONE_DAY_IN_SEC_F64 } + #[inline] pub fn is_more_than_hour(&self) -> bool { - jiff::Timestamp::from(*self).as_second() >= 60 * 60 + self.0 >= ONE_HOUR_IN_SEC } } diff --git a/crates/brk_logger/src/lib.rs b/crates/brk_logger/src/lib.rs index ab1862bf7..c11b29ad8 100644 --- a/crates/brk_logger/src/lib.rs +++ b/crates/brk_logger/src/lib.rs @@ -14,7 +14,7 @@ use color_eyre::owo_colors::OwoColorize; use env_logger::{Builder, Env}; use jiff::{Timestamp, tz}; -#[inline(always)] +#[inline] pub fn init(path: Option<&Path>) { let file = path.map(|path| { let _ = fs::remove_file(path); diff --git a/crates/brk_parser/src/xor_index.rs b/crates/brk_parser/src/xor_index.rs index 81b79498d..0ce4cf682 100644 --- a/crates/brk_parser/src/xor_index.rs +++ b/crates/brk_parser/src/xor_index.rs @@ -17,14 +17,14 @@ impl XORIndex { bytes } - #[inline(always)] + #[inline] pub fn byte(&mut self, mut byte: u8, xor_bytes: &XORBytes) -> u8 { byte ^= xor_bytes[self.0]; self.increment(); byte } - #[inline(always)] + #[inline] pub fn increment(&mut self) { self.0 += 1; if self.0 == XOR_LEN { @@ -32,7 +32,7 @@ impl XORIndex { } } - #[inline(always)] + #[inline] pub fn add_assign(&mut self, i: usize) { self.0 = (self.0 + i) % XOR_LEN; } diff --git a/crates/brk_vec/src/traits/generic.rs b/crates/brk_vec/src/traits/generic.rs index fcb9ca0c9..576740c89 100644 --- a/crates/brk_vec/src/traits/generic.rs +++ b/crates/brk_vec/src/traits/generic.rs @@ -22,6 +22,10 @@ where { const SIZE_OF_T: usize = size_of::(); + #[inline] + fn unwrap_read(&self, index: I, mmap: &Mmap) -> T { + self.read(index, mmap).unwrap().unwrap() + } #[inline] fn read(&self, index: I, mmap: &Mmap) -> Result> { self.read_(index.to_usize()?, mmap) diff --git a/crates/brk_vec/src/variants/compressed.rs b/crates/brk_vec/src/variants/compressed.rs index 29d9b5905..ec3e52fc2 100644 --- a/crates/brk_vec/src/variants/compressed.rs +++ b/crates/brk_vec/src/variants/compressed.rs @@ -120,12 +120,12 @@ where zstd::encode_all(bytes.as_slice(), DEFAULT_COMPRESSION_LEVEL).unwrap() } - #[inline(always)] + #[inline] fn index_to_page_index(index: usize) -> usize { index / Self::PER_PAGE } - #[inline(always)] + #[inline] fn page_index_to_index(page_index: usize) -> usize { page_index * Self::PER_PAGE } diff --git a/crates/brk_vec/src/variants/eager.rs b/crates/brk_vec/src/variants/eager.rs index befdff8a2..eec317497 100644 --- a/crates/brk_vec/src/variants/eager.rs +++ b/crates/brk_vec/src/variants/eager.rs @@ -24,7 +24,7 @@ use crate::{ const ONE_KIB: usize = 1024; const ONE_MIB: usize = ONE_KIB * ONE_KIB; -const MAX_CACHE_SIZE: usize = 210 * ONE_MIB; +const MAX_CACHE_SIZE: usize = 256 * ONE_MIB; const DCA_AMOUNT: Dollars = Dollars::mint(100.0); #[derive(Debug, Clone)] diff --git a/crates/brk_vec/src/variants/indexed.rs b/crates/brk_vec/src/variants/indexed.rs index 8be6e1b8c..32aa0d007 100644 --- a/crates/brk_vec/src/variants/indexed.rs +++ b/crates/brk_vec/src/variants/indexed.rs @@ -29,6 +29,11 @@ where )) } + #[inline] + pub fn unwrap_read(&self, index: I, mmap: &Mmap) -> T { + self.0.unwrap_read(index, mmap) + } + #[inline] pub fn get_or_read(&self, index: I, mmap: &Mmap) -> Result>> { self.0.get_or_read(index, mmap)