Skip to content

Ve/alloc count#125

Open
vladimir-ea wants to merge 9 commits into
mainfrom
ve/alloc_count
Open

Ve/alloc count#125
vladimir-ea wants to merge 9 commits into
mainfrom
ve/alloc_count

Conversation

@vladimir-ea

Copy link
Copy Markdown
Collaborator

add a counting allocator with per thread counters exported to surfer

Comment thread crates/bin/src/main.rs
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
// #[cfg(not(feature = "alloc-profile"))]
// #[global_allocator]
// static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to using CountingAllocator in this PR - possibly counting allocator should be put behind a feature flag ..

Comment thread crates/metrics/src/lib.rs
/// `init` / `init_with_base` force the map early (and let tests redirect the
/// base dir) for the calling thread only.
#[macro_export]
macro_rules! declare_thread_counters {

@alexX512 alexX512 Jun 26, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need that big macro? It feels like for our use case we can use small counter in shared memory with specific file name like in allocator file

const BYTES: usize = std::mem::size_of::<AtomicI64>();

thread_local! {
    static BASE: Cell<*mut AtomicI64> = const { Cell::new(null_mut()) };
}

#[inline]
fn cell() -> &'static AtomicI64 {
    let p = BASE.with(|c| {
        let p = c.get();
        if !p.is_null() {
            return p;             
        }
        let p = map_this_thread();   
        c.set(p);
        p
    });
    unsafe { &*p }
}

#[cold]
fn map_this_thread() -> *mut AtomicI64 {
    let t = std::thread::current();
    let file = match t.name() {
        Some(n) => format!("{n}_allocator"),
        None => format!("{:?}_allocator", t.id()),
    };
    mmap_counters_file(local_share_dir().as_ref(), "silver", &file, BYTES)
        .map(|p| p.cast::<AtomicI64>())
        .expect("alloc counter mmap")
}

pub fn add(n: i64) { cell().fetch_add(n, Relaxed); }
pub fn sub(n: i64) { cell().fetch_sub(n, Relaxed); }
pub fn get() -> i64 { cell().load(Relaxed) }

Comment thread crates/metrics/src/lib.rs
x + 1
}

#[timed("timed_sampled_label", sample = 1000)]

@alexX512 alexX512 Jun 26, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sampled label was removed from timed macro as we never used it in prod and with it it might be hard to analyse results as in flamegraphs we track how many time a function was called

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants