mod common;
use std::alloc::{GlobalAlloc, Layout};
use std::hint::black_box;
use stoolap_jemalloc::{Jemalloc, prof};
#[global_allocator]
static GLOBAL: Jemalloc = Jemalloc::new();
#[inline(never)]
fn allocate_on_path(path: u32, depth: u32) -> Vec<u8> {
if depth == 0 {
vec![path as u8; 64]
} else if path & 1 == 0 {
black_box(left(path >> 1, depth - 1))
} else {
black_box(right(path >> 1, depth - 1))
}
}
#[inline(never)]
fn left(path: u32, depth: u32) -> Vec<u8> {
let v = allocate_on_path(path, depth);
black_box(&v);
v
}
#[inline(never)]
fn right(path: u32, depth: u32) -> Vec<u8> {
let v = allocate_on_path(path, depth);
black_box(v.len());
v
}
#[test]
fn every_kind_of_sampled_allocation() {
assert!(!prof::is_active());
let err = prof::dump_pprof().unwrap_err();
assert_eq!(err.to_string(), "heap profiling was never activated");
prof::set_sample_interval(1);
assert_eq!(prof::sample_interval(), 1);
prof::activate();
assert!(prof::is_active());
drop(black_box(vec![0u8; 2 << 20]));
let boxes: Vec<_> = (0..1024).map(|path| allocate_on_path(path, 10)).collect();
unsafe {
for (size, align) in [(1000, 8), (5000, 8192), (3 << 20, 8), (100, 1 << 21)] {
let layout = Layout::from_size_align(size, align).unwrap();
let p = GLOBAL.alloc_zeroed(layout);
assert_eq!(p as usize % align, 0);
assert!((0..size).step_by(97).all(|i| *p.add(i) == 0));
p.write_bytes(5, size);
let q = GLOBAL.realloc(p, layout, size + 1);
assert_eq!(q as usize % align, 0);
assert!((0..size).step_by(97).all(|i| *q.add(i) == 5));
GLOBAL.dealloc(q, Layout::from_size_align(size + 1, align).unwrap());
}
}
prof::deactivate();
assert!(!prof::is_active());
let profile = prof::dump_pprof().unwrap();
#[cfg(feature = "symbolize")]
assert!(String::from_utf8_lossy(&profile).contains("allocate_on_path"));
let samples = common::fields(&profile)
.iter()
.filter(|(field, _)| *field == 2)
.count();
assert!(samples >= 1024, "{samples} samples");
drop(boxes);
let err = prof::write_pprof("/nonexistent-dir/heap.pb").unwrap_err();
assert!(matches!(err, prof::DumpError::Io(_)));
assert!(err.to_string().starts_with("writing the heap profile"));
}