dataprof_core/sampling/strategies.rs
1/// How rows are selected for profiling.
2///
3/// Strategies divide into two families, which differ in cost.
4/// [`Systematic`](Self::Systematic) decides each row as it arrives and adds no
5/// memory. [`Random`](Self::Random) and [`Reservoir`](Self::Reservoir) cannot
6/// know the final sample until the source ends, so they hold `size` rows in
7/// memory and the profile is computed from that buffer.
8///
9/// Every strategy is applied by `RowSampler`.
10#[derive(Debug, Clone)]
11pub enum SamplingStrategy {
12 /// No sampling - analyze all data
13 None,
14
15 /// A uniform random sample of exactly `size` rows (or every row, when the
16 /// source is shorter).
17 ///
18 /// Over a source of unknown length this is reservoir sampling, so it holds
19 /// `size` rows in memory and is equivalent to
20 /// [`Reservoir`](Self::Reservoir); both names are kept because both are
21 /// familiar.
22 Random { size: usize },
23
24 /// A uniform random sample of exactly `size` rows, selected with Algorithm
25 /// R over a single pass.
26 ///
27 /// Holds `size` rows in memory: membership is not final until the source
28 /// ends, and statistics folded in earlier could not be retracted.
29 Reservoir { size: usize },
30
31 /// Every `interval`-th row, starting at the first.
32 Systematic { interval: usize },
33}
34
35impl SamplingStrategy {
36 /// Get description of the sampling strategy
37 pub fn description(&self) -> String {
38 match self {
39 SamplingStrategy::None => "Full dataset analysis".to_string(),
40 SamplingStrategy::Random { size } => format!("Random sampling ({} records)", size),
41 SamplingStrategy::Reservoir { size } => {
42 format!("Reservoir sampling ({} records)", size)
43 }
44 SamplingStrategy::Systematic { interval } => {
45 format!("Systematic (every {}th record)", interval)
46 }
47 }
48 }
49}