use crate::heap::Stats;
use crate::options::out_fmt;
pub fn merged() -> Stats {
let mut total = Stats::new();
crate::init::for_each_heap(&mut |h| {
let s = h.stats;
total.allocs += s.allocs;
total.frees += s.frees;
total.generic += s.generic;
total.pages_fresh += s.pages_fresh;
total.segments += s.segments;
total.huge_allocs += s.huge_allocs;
total.extends += s.extends;
total.large_allocs += s.large_allocs;
total.pages_retired += s.pages_retired;
total.segments_freed += s.segments_freed;
total.realloc_in_place += s.realloc_in_place;
total.realloc_moved += s.realloc_moved;
total.delayed_frees += s.delayed_frees;
total.reclaims += s.reclaims;
});
total
}
fn print_one(label: &str, s: &Stats) {
out_fmt(&format!(
"{label}: allocs {} frees {} (generic {}), pages fresh {} retired {}, \
segments {} freed {}, large {} huge {}, realloc {}/{} (in-place/moved), \
delayed {} reclaims {}\n",
s.allocs,
s.frees,
s.generic,
s.pages_fresh,
s.pages_retired,
s.segments,
s.segments_freed,
s.large_allocs,
s.huge_allocs,
s.realloc_in_place,
s.realloc_moved,
s.delayed_frees,
s.reclaims,
));
}
pub fn print_process() {
let m = merged();
print_one("heap stats (process)", &m);
let (elapsed, user, sys, rss, peak_rss, commit, peak_commit, faults) = process_info();
out_fmt(&format!(
"process: elapsed {elapsed} ms, user {user} ms, sys {sys} ms, rss {} KiB (peak {}), \
commit {} KiB (peak {}), faults {faults}\n",
rss / 1024,
peak_rss / 1024,
commit / 1024,
peak_commit / 1024,
));
}
pub fn print_thread() {
let s = crate::alloc::stats();
print_one("heap stats (thread)", &s);
}
pub fn reset() {
unsafe {
let hb = crate::init::heap_box();
(*(*hb).heap.get()).stats = Stats::new();
}
}
pub fn process_info() -> (usize, usize, usize, usize, usize, usize, usize, usize) {
#[cfg(all(windows, not(miri)))]
{
win_process_info()
}
#[cfg(all(unix, not(miri)))]
{
unix_process_info()
}
#[cfg(any(miri, all(target_arch = "wasm32", not(miri))))]
{
(0, 0, 0, 0, 0, 0, 0, 0)
}
}
#[cfg(all(windows, not(miri)))]
fn win_process_info() -> (usize, usize, usize, usize, usize, usize, usize, usize) {
use windows_sys::Win32::System::ProcessStatus::{
K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS,
};
use windows_sys::Win32::System::Threading::{GetCurrentProcess, GetProcessTimes};
unsafe {
let proc = GetCurrentProcess();
let (mut c, mut e, mut k, mut u) = ([0u32; 2], [0u32; 2], [0u32; 2], [0u32; 2]);
GetProcessTimes(
proc,
c.as_mut_ptr().cast(),
e.as_mut_ptr().cast(),
k.as_mut_ptr().cast(),
u.as_mut_ptr().cast(),
);
let ft = |t: [u32; 2]| ((t[1] as u64) << 32 | t[0] as u64) / 10_000; let mut pmc: PROCESS_MEMORY_COUNTERS = core::mem::zeroed();
pmc.cb = core::mem::size_of::<PROCESS_MEMORY_COUNTERS>() as u32;
K32GetProcessMemoryInfo(proc, &mut pmc, pmc.cb);
let now = crate::prim::clock_now() / 1_000_000;
(
now as usize,
ft(u) as usize,
ft(k) as usize,
pmc.WorkingSetSize,
pmc.PeakWorkingSetSize,
pmc.PagefileUsage,
pmc.PeakPagefileUsage,
pmc.PageFaultCount as usize,
)
}
}
#[cfg(all(unix, not(miri)))]
fn unix_process_info() -> (usize, usize, usize, usize, usize, usize, usize, usize) {
unsafe {
let mut ru: libc::rusage = core::mem::zeroed();
libc::getrusage(libc::RUSAGE_SELF, &mut ru);
let ms = |tv: libc::timeval| (tv.tv_sec as usize) * 1000 + (tv.tv_usec as usize) / 1000;
#[cfg(target_vendor = "apple")]
#[allow(deprecated)]
let (current_rss, peak_rss) = {
let mut info: libc::mach_task_basic_info = core::mem::zeroed();
let mut count = libc::MACH_TASK_BASIC_INFO_COUNT;
let kr = libc::task_info(
libc::mach_task_self_,
libc::MACH_TASK_BASIC_INFO as libc::task_flavor_t,
(&raw mut info).cast(),
&mut count,
);
if kr == libc::KERN_SUCCESS {
(info.resident_size as usize, info.resident_size_max as usize)
} else {
(0, 0) }
};
#[cfg(not(target_vendor = "apple"))]
let (current_rss, peak_rss) = {
let peak = (ru.ru_maxrss as usize) * 1024;
let current = std::fs::read_to_string("/proc/self/statm")
.ok()
.and_then(|s| {
s.split_whitespace()
.nth(1)
.and_then(|v| v.parse::<usize>().ok())
})
.map(|pages| pages * crate::os::page_size())
.unwrap_or(0);
(current, peak)
};
let now = crate::prim::clock_now() / 1_000_000;
(
now as usize,
ms(ru.ru_utime),
ms(ru.ru_stime),
current_rss,
peak_rss,
0,
0,
(ru.ru_majflt + ru.ru_minflt) as usize,
)
}
}