Skip to main content

HyperLogLog

Struct HyperLogLog 

Source
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 implement Hash).

  • H: the BuildHasher used to hash elements.

  • W: the unsigned word type for the register backend (see below).

  • BETA: when true (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 to false via HyperLogLogBuilder::beta to 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>

Source

pub fn log2_num_regs(&self) -> u32

Returns the base-2 logarithm of the number of registers per estimator.

Source§

impl HyperLogLog<(), (), (), true>

Source

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.
Source

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.
Source

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: Clone, W: Clone, const BETA: bool> Clone for HyperLogLog<T, H, W, BETA>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug, H: Debug, W: Debug, const BETA: bool> Debug for HyperLogLog<T, H, W, BETA>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T, H, W, const BETA: bool> Display for HyperLogLog<T, H, W, BETA>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Hash, H: BuildHasher + Clone, W: Word, const BETA: bool> EstimationLogic for HyperLogLog<T, H, W, BETA>

Source§

type Item = T

The type of items.
Source§

type Backend = [W]

The type of the backend.
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

The type of an estimator.
Source§

fn new_estimator(&self) -> Self::Estimator<'_>

Creates a new empty estimator using this logic.
Source§

fn add(&self, backend: &mut Self::Backend, element: impl Borrow<T>)

Adds an element to an estimator with the given backend.
Source§

fn estimate(&self, backend: &[W]) -> f64

Returns an estimation of the number of distinct elements that have been added to an estimator with the given backend so far.
Source§

fn clear(&self, backend: &mut [W])

Clears a backend, making it empty.
Source§

fn set(&self, dst: &mut [W], src: &[W])

Sets the contents of dst to the contents of src.
Source§

impl<T: Hash, H: BuildHasher + Clone, W: Word, const BETA: bool> MergeEstimationLogic for HyperLogLog<T, H, W, BETA>

Source§

type Helper = HyperLogLogHelper<W>

The type of the helper used in merge calculations. Read more
Source§

fn new_helper(&self) -> Self::Helper

Creates a new helper to use in merge operations.
Source§

fn merge_with_helper(&self, dst: &mut [W], src: &[W], helper: &mut Self::Helper)

Merges src into dst using the provided helper to avoid allocations.
Source§

fn merge(&self, dst: &mut Self::Backend, src: &Self::Backend)

Merges src into dst.
Source§

impl<T: PartialEq, H: PartialEq, W: PartialEq, const BETA: bool> PartialEq for HyperLogLog<T, H, W, BETA>

Source§

fn eq(&self, other: &HyperLogLog<T, H, W, BETA>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T: Hash, H: BuildHasher + Clone, W: Word, const BETA: bool> SliceEstimationLogic<W> for HyperLogLog<T, H, W, BETA>

Source§

fn backend_len(&self) -> usize

The number of elements of type T in a backend.
Source§

impl<T, H, W, const BETA: bool> StructuralPartialEq for HyperLogLog<T, H, W, BETA>

Auto Trait Implementations§

§

impl<T, H, W, const BETA: bool> Freeze for HyperLogLog<T, H, W, BETA>
where H: Freeze,

§

impl<T, H, W, const BETA: bool> RefUnwindSafe for HyperLogLog<T, H, W, BETA>

§

impl<T, H, W, const BETA: bool> Send for HyperLogLog<T, H, W, BETA>
where H: Send, T: Send, W: Send,

§

impl<T, H, W, const BETA: bool> Sync for HyperLogLog<T, H, W, BETA>
where H: Sync, T: Sync, W: Sync,

§

impl<T, H, W, const BETA: bool> Unpin for HyperLogLog<T, H, W, BETA>
where H: Unpin, T: Unpin,

§

impl<T, H, W, const BETA: bool> UnsafeUnpin for HyperLogLog<T, H, W, BETA>
where H: UnsafeUnpin,

§

impl<T, H, W, const BETA: bool> UnwindSafe for HyperLogLog<T, H, W, BETA>
where H: UnwindSafe, T: UnwindSafe, W: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.