milli_core/
database_stats.rs

1use std::mem;
2
3use heed::Database;
4use heed::DatabaseStat;
5use heed::RoTxn;
6use heed::Unspecified;
7use serde::{Deserialize, Serialize};
8
9use crate::BEU32;
10
11#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
12#[serde(rename_all = "camelCase")]
13/// The stats of a database.
14pub struct DatabaseStats {
15    /// The number of entries in the database.
16    number_of_entries: u64,
17    /// The total size of the keys in the database.
18    total_key_size: u64,
19    /// The total size of the values in the database.
20    total_value_size: u64,
21}
22
23impl DatabaseStats {
24    /// Returns the stats of the database.
25    ///
26    /// This function iterates over the whole database and computes the stats.
27    /// It is not efficient and should be cached somewhere.
28    pub(crate) fn new(
29        database: Database<BEU32, Unspecified>,
30        rtxn: &RoTxn<'_>,
31    ) -> heed::Result<Self> {
32        let DatabaseStat { page_size, depth: _, branch_pages, leaf_pages, overflow_pages, entries } =
33            database.stat(rtxn)?;
34
35        // We first take the total size without overflow pages as the overflow pages contains the values and only that.
36        let total_size = (branch_pages + leaf_pages + overflow_pages) * page_size as usize;
37        // We compute an estimated size for the keys.
38        let total_key_size = entries * (mem::size_of::<u32>() + 4);
39        let total_value_size = total_size - total_key_size;
40
41        Ok(Self {
42            number_of_entries: entries as u64,
43            total_key_size: total_key_size as u64,
44            total_value_size: total_value_size as u64,
45        })
46    }
47
48    pub fn average_key_size(&self) -> u64 {
49        self.total_key_size.checked_div(self.number_of_entries).unwrap_or(0)
50    }
51
52    pub fn average_value_size(&self) -> u64 {
53        self.total_value_size.checked_div(self.number_of_entries).unwrap_or(0)
54    }
55
56    pub fn number_of_entries(&self) -> u64 {
57        self.number_of_entries
58    }
59
60    pub fn total_size(&self) -> u64 {
61        self.total_key_size + self.total_value_size
62    }
63
64    pub fn total_key_size(&self) -> u64 {
65        self.total_key_size
66    }
67
68    pub fn total_value_size(&self) -> u64 {
69        self.total_value_size
70    }
71}