pub struct HyperLogLog<T, H, W = usize, const BETA: bool = true> { /* private fields */ }Expand description
Estimation logic implementing the HyperLogLog algorithm.
This implementation uses 5- or 6-bit registers and broadword
programming. It thus uses the
minimum possible space, saving 37.5 or 25% space with respect to the
HyperLogLog8 logic, which uses 8-bit
registers and byte-wise SIMD operations, but it is significantly slower than
the latter.
The choice between the two logics should be guided by the specific use case and constraints of your application. Please try the included benchmarks to have an idea of the difference in performance between the two logics in your environment.
Instances are created through HyperLogLogBuilder:
// Default: LogLog-β correction enabled, usize backend
let logic = HyperLogLogBuilder::new(1_000_000)
.log2_num_regs(8)
.build::<String>().unwrap();
// Disable LogLog-β, use classic HyperLogLog + linear-counting fallback
let logic = HyperLogLogBuilder::new(1_000_000)
.log2_num_regs(8)
.beta::<false>()
.build::<String>().unwrap();§Type parameters
-
T: the type of elements to count (must implementHash). -
H: theBuildHasherused to hash elements. -
W: the unsigned word type for the register backend (see below). -
BETA: whentrue(the default), the LogLog-β bias correction is used during estimation. This provides better accuracy across the full cardinality range through a single formula, eliminating the need for a separate linear-counting correction. The cost is roughly 20ns per estimate call when some registers are still zero; when all registers are populated, the correction is skipped and performance is identical to the classic formula. Set tofalseviaHyperLogLogBuilder::betato use the original HyperLogLog formula instead.
§Backend alignment
W must be able to represent exactly the backend of an estimator. While
usually usize will work (and it is the default type chosen by
HyperLogLogBuilder::new), with odd register sizes and a small number
of registers it might be necessary to select a smaller type, resulting in
slower merges. For example, using 16 5-bit registers one needs to use
u16, whereas for 16 6-bit registers u32 will be sufficient.
Formally, W::BITS must divide (1 << log2_num_regs) * register_size
(using HyperLogLog::register_size(num_elements)).
HyperLogLogBuilder::min_log2_num_regs returns the minimum value for
log2_num_regs that satisfies this property.
Implementations§
Source§impl<T, H: Clone, W: Word, const BETA: bool> HyperLogLog<T, H, W, BETA>
impl<T, H: Clone, W: Word, const BETA: bool> HyperLogLog<T, H, W, BETA>
Sourcepub fn log2_num_regs(&self) -> u32
pub fn log2_num_regs(&self) -> u32
Returns the base-2 logarithm of the number of registers per estimator.
Source§impl HyperLogLog<(), (), (), true>
impl HyperLogLog<(), (), (), true>
Sourcepub fn log2_num_of_registers(rsd: f64) -> u32
pub fn log2_num_of_registers(rsd: f64) -> u32
Returns the logarithm of the number of registers per estimator that are necessary to attain a given relative standard deviation.
§Arguments
rsd: the relative standard deviation to be attained.
Sourcepub fn rel_std(log2_num_regs: u32) -> f64
pub fn rel_std(log2_num_regs: u32) -> f64
Returns the relative standard deviation corresponding to a given number of registers per estimator.
§Arguments
log2_num_regs: the logarithm of the number of registers per estimator.
Sourcepub fn register_size(num_elements: usize) -> usize
pub fn register_size(num_elements: usize) -> usize
Returns the register size in bits, given an upper bound on the number of distinct elements.
§Arguments
num_elements: an upper bound on the number of distinct elements.
Trait Implementations§
Source§impl<T, H, W, const BETA: bool> Display for HyperLogLog<T, H, W, BETA>
impl<T, H, W, const BETA: bool> Display for HyperLogLog<T, H, W, BETA>
Source§impl<T: Hash, H: BuildHasher + Clone, W: Word, const BETA: bool> EstimationLogic for HyperLogLog<T, H, W, BETA>where
u32: PrimitiveNumberAs<W>,
impl<T: Hash, H: BuildHasher + Clone, W: Word, const BETA: bool> EstimationLogic for HyperLogLog<T, H, W, BETA>where
u32: PrimitiveNumberAs<W>,
Source§type Estimator<'a> = DefaultEstimator<HyperLogLog<T, H, W, BETA>, &'a HyperLogLog<T, H, W, BETA>, Box<[W]>>
where
T: 'a,
W: 'a,
H: 'a
type Estimator<'a> = DefaultEstimator<HyperLogLog<T, H, W, BETA>, &'a HyperLogLog<T, H, W, BETA>, Box<[W]>> where T: 'a, W: 'a, H: 'a
Source§fn new_estimator(&self) -> Self::Estimator<'_>
fn new_estimator(&self) -> Self::Estimator<'_>
Source§fn add(&self, backend: &mut Self::Backend, element: impl Borrow<T>)
fn add(&self, backend: &mut Self::Backend, element: impl Borrow<T>)
Source§impl<T: Hash, H: BuildHasher + Clone, W: Word, const BETA: bool> MergeEstimationLogic for HyperLogLog<T, H, W, BETA>where
u32: PrimitiveNumberAs<W>,
impl<T: Hash, H: BuildHasher + Clone, W: Word, const BETA: bool> MergeEstimationLogic for HyperLogLog<T, H, W, BETA>where
u32: PrimitiveNumberAs<W>,
Source§type Helper = HyperLogLogHelper<W>
type Helper = HyperLogLogHelper<W>
Source§fn new_helper(&self) -> Self::Helper
fn new_helper(&self) -> Self::Helper
Source§impl<T: PartialEq, H: PartialEq, W: PartialEq, const BETA: bool> PartialEq for HyperLogLog<T, H, W, BETA>
impl<T: PartialEq, H: PartialEq, W: PartialEq, const BETA: bool> PartialEq for HyperLogLog<T, H, W, BETA>
Source§impl<T: Hash, H: BuildHasher + Clone, W: Word, const BETA: bool> SliceEstimationLogic<W> for HyperLogLog<T, H, W, BETA>where
u32: PrimitiveNumberAs<W>,
impl<T: Hash, H: BuildHasher + Clone, W: Word, const BETA: bool> SliceEstimationLogic<W> for HyperLogLog<T, H, W, BETA>where
u32: PrimitiveNumberAs<W>,
Source§fn backend_len(&self) -> usize
fn backend_len(&self) -> usize
T in a backend.