mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 22:59:58 -07:00
global: snapshot
This commit is contained in:
120
crates/brk_computer/src/internal/group/distribution.rs
Normal file
120
crates/brk_computer/src/internal/group/distribution.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
use brk_error::Result;
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
Database, Exit, ReadableVec, Ro, Rw, VecIndex, VecValue, Version,
|
||||
};
|
||||
|
||||
use crate::internal::{
|
||||
AverageVec, ComputedVecValue, DistributionStats, MaxVec, MedianVec, MinVec, Pct10Vec,
|
||||
Pct25Vec, Pct75Vec, Pct90Vec,
|
||||
};
|
||||
|
||||
/// Distribution stats (average + min + max + percentiles) — concrete vec type alias.
|
||||
pub type Distribution<I, T, M = Rw> = DistributionStats<
|
||||
AverageVec<I, T, M>,
|
||||
MinVec<I, T, M>,
|
||||
MaxVec<I, T, M>,
|
||||
Pct10Vec<I, T, M>,
|
||||
Pct25Vec<I, T, M>,
|
||||
MedianVec<I, T, M>,
|
||||
Pct75Vec<I, T, M>,
|
||||
Pct90Vec<I, T, M>,
|
||||
>;
|
||||
|
||||
impl<I: VecIndex, T: ComputedVecValue + JsonSchema> Distribution<I, T> {
|
||||
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
|
||||
Ok(Self {
|
||||
average: AverageVec::forced_import(db, name, version)?,
|
||||
min: MinVec::forced_import(db, name, version)?,
|
||||
max: MaxVec::forced_import(db, name, version)?,
|
||||
pct10: Pct10Vec::forced_import(db, name, version)?,
|
||||
pct25: Pct25Vec::forced_import(db, name, version)?,
|
||||
median: MedianVec::forced_import(db, name, version)?,
|
||||
pct75: Pct75Vec::forced_import(db, name, version)?,
|
||||
pct90: Pct90Vec::forced_import(db, name, version)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute distribution stats, skipping first N items from all calculations.
|
||||
///
|
||||
/// Use `skip_count: 1` to exclude coinbase transactions from fee/feerate stats.
|
||||
pub(crate) fn compute_with_skip<A>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &impl ReadableVec<A, T>,
|
||||
first_indexes: &impl ReadableVec<I, A>,
|
||||
count_indexes: &impl ReadableVec<I, brk_types::StoredU64>,
|
||||
exit: &Exit,
|
||||
skip_count: usize,
|
||||
) -> Result<()>
|
||||
where
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
crate::internal::compute_aggregations(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
exit,
|
||||
skip_count,
|
||||
None, // first
|
||||
None, // last
|
||||
Some(&mut self.min.0),
|
||||
Some(&mut self.max.0),
|
||||
Some(&mut self.average.0),
|
||||
None, // sum
|
||||
None, // cumulative
|
||||
Some(&mut self.median.0),
|
||||
Some(&mut self.pct10.0),
|
||||
Some(&mut self.pct25.0),
|
||||
Some(&mut self.pct75.0),
|
||||
Some(&mut self.pct90.0),
|
||||
)
|
||||
}
|
||||
|
||||
/// Compute distribution stats from a fixed n-block rolling window.
|
||||
///
|
||||
/// For each index `i`, aggregates all source items from blocks `max(0, i - n_blocks + 1)..=i`.
|
||||
pub(crate) fn compute_from_nblocks<A>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &impl ReadableVec<A, T>,
|
||||
first_indexes: &impl ReadableVec<I, A>,
|
||||
count_indexes: &impl ReadableVec<I, brk_types::StoredU64>,
|
||||
n_blocks: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
crate::internal::compute_aggregations_nblock_window(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
n_blocks,
|
||||
exit,
|
||||
&mut self.min.0,
|
||||
&mut self.max.0,
|
||||
&mut self.average.0,
|
||||
&mut self.median.0,
|
||||
&mut self.pct10.0,
|
||||
&mut self.pct25.0,
|
||||
&mut self.pct75.0,
|
||||
&mut self.pct90.0,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn read_only_clone(&self) -> Distribution<I, T, Ro> {
|
||||
DistributionStats {
|
||||
average: self.average.read_only_clone(),
|
||||
min: self.min.read_only_clone(),
|
||||
max: self.max.read_only_clone(),
|
||||
pct10: self.pct10.read_only_clone(),
|
||||
pct25: self.pct25.read_only_clone(),
|
||||
median: self.median.read_only_clone(),
|
||||
pct75: self.pct75.read_only_clone(),
|
||||
pct90: self.pct90.read_only_clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
71
crates/brk_computer/src/internal/group/full.rs
Normal file
71
crates/brk_computer/src/internal/group/full.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, ReadableVec, Ro, Rw, StorageMode, VecIndex, VecValue, Version};
|
||||
|
||||
use crate::internal::ComputedVecValue;
|
||||
|
||||
use super::{Distribution, SumCumulative};
|
||||
|
||||
/// Full stats aggregate: distribution + sum_cumulative
|
||||
/// Matches the common full_stats() pattern: average + minmax + percentiles + sum + cumulative
|
||||
#[derive(Traversable)]
|
||||
pub struct Full<I: VecIndex, T: ComputedVecValue + JsonSchema, M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub distribution: Distribution<I, T, M>,
|
||||
#[traversable(flatten)]
|
||||
pub sum_cumulative: SumCumulative<I, T, M>,
|
||||
}
|
||||
|
||||
impl<I: VecIndex, T: ComputedVecValue + JsonSchema> Full<I, T> {
|
||||
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
|
||||
Ok(Self {
|
||||
distribution: Distribution::forced_import(db, name, version)?,
|
||||
sum_cumulative: SumCumulative::forced_import(db, name, version)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute all stats, skipping first N items from all calculations.
|
||||
///
|
||||
/// Use `skip_count: 1` to exclude coinbase transactions from fee/feerate stats.
|
||||
pub(crate) fn compute_with_skip<A>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &impl ReadableVec<A, T>,
|
||||
first_indexes: &impl ReadableVec<I, A>,
|
||||
count_indexes: &impl ReadableVec<I, brk_types::StoredU64>,
|
||||
exit: &Exit,
|
||||
skip_count: usize,
|
||||
) -> Result<()>
|
||||
where
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
crate::internal::compute_aggregations(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
exit,
|
||||
skip_count,
|
||||
None, // first
|
||||
None, // last
|
||||
Some(&mut self.distribution.min.0),
|
||||
Some(&mut self.distribution.max.0),
|
||||
Some(&mut self.distribution.average.0),
|
||||
Some(&mut self.sum_cumulative.sum.0),
|
||||
Some(&mut self.sum_cumulative.cumulative.0),
|
||||
Some(&mut self.distribution.median.0),
|
||||
Some(&mut self.distribution.pct10.0),
|
||||
Some(&mut self.distribution.pct25.0),
|
||||
Some(&mut self.distribution.pct75.0),
|
||||
Some(&mut self.distribution.pct90.0),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn read_only_clone(&self) -> Full<I, T, Ro> {
|
||||
Full {
|
||||
distribution: self.distribution.read_only_clone(),
|
||||
sum_cumulative: self.sum_cumulative.read_only_clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
7
crates/brk_computer/src/internal/group/mod.rs
Normal file
7
crates/brk_computer/src/internal/group/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
mod distribution;
|
||||
mod full;
|
||||
mod sum_cumulative;
|
||||
|
||||
pub use distribution::*;
|
||||
pub use full::*;
|
||||
pub use sum_cumulative::*;
|
||||
31
crates/brk_computer/src/internal/group/sum_cumulative.rs
Normal file
31
crates/brk_computer/src/internal/group/sum_cumulative.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Ro, Rw, StorageMode, VecIndex, Version};
|
||||
|
||||
use crate::internal::{ComputedVecValue, CumulativeVec, SumVec};
|
||||
|
||||
/// Sum + Cumulative (12% of usage)
|
||||
#[derive(Traversable)]
|
||||
pub struct SumCumulative<I: VecIndex, T: ComputedVecValue + JsonSchema, M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub sum: SumVec<I, T, M>,
|
||||
#[traversable(flatten)]
|
||||
pub cumulative: CumulativeVec<I, T, M>,
|
||||
}
|
||||
|
||||
impl<I: VecIndex, T: ComputedVecValue + JsonSchema> SumCumulative<I, T> {
|
||||
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
|
||||
Ok(Self {
|
||||
sum: SumVec::forced_import(db, name, version)?,
|
||||
cumulative: CumulativeVec::forced_import(db, name, version)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn read_only_clone(&self) -> SumCumulative<I, T, Ro> {
|
||||
SumCumulative {
|
||||
sum: self.sum.read_only_clone(),
|
||||
cumulative: self.cumulative.read_only_clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user