Skip to main content

stoolap_jemalloc/
stats.rs

1// Copyright 2026 Stoolap Contributors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Process-wide counters, updated only on slow paths
16
17use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
18
19pub(crate) static CHUNK_BYTES: Counter = Counter::new();
20pub(crate) static HUGE_BYTES: Counter = Counter::new();
21pub(crate) static HUGE_CACHED_BYTES: Counter = Counter::new();
22pub(crate) static METADATA_BYTES: Counter = Counter::new();
23
24/// Memory the allocator holds from the OS, in bytes
25#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
26pub struct Stats {
27    /// Chunks that hold small and large allocations
28    pub chunks: usize,
29    /// Mappings of huge allocations that are in use
30    pub huge: usize,
31    /// Freed huge mappings kept for reuse
32    pub huge_cached: usize,
33    /// The allocator's own metadata, including the heap profiler's
34    pub metadata: usize,
35}
36
37impl Stats {
38    /// All memory mapped from the OS
39    #[must_use]
40    pub fn mapped(&self) -> usize {
41        self.chunks + self.huge + self.huge_cached + self.metadata
42    }
43}
44
45/// A snapshot of the allocator's counters
46pub fn stats() -> Stats {
47    Stats {
48        chunks: CHUNK_BYTES.get(),
49        huge: HUGE_BYTES.get(),
50        huge_cached: HUGE_CACHED_BYTES.get(),
51        metadata: METADATA_BYTES.get(),
52    }
53}
54
55/// A counter of bytes. Additions and subtractions are separate so that no
56/// size needs a sign: on 32-bit targets a mapping can exceed `isize::MAX`.
57pub(crate) struct Counter(AtomicUsize);
58
59impl Counter {
60    const fn new() -> Self {
61        Counter(AtomicUsize::new(0))
62    }
63
64    fn get(&self) -> usize {
65        self.0.load(Relaxed)
66    }
67
68    pub(crate) fn add(&self, n: usize) {
69        self.0.fetch_add(n, Relaxed);
70    }
71
72    pub(crate) fn sub(&self, n: usize) {
73        self.0.fetch_sub(n, Relaxed);
74    }
75}