我注意到Rust的测试有一个基准模式,可以测量ns/iter
中的执行时间,但我找不到一种方法来测量内存使用情况。
我如何实施这样的基准?让我们假设目前我只关心堆内存(虽然堆栈使用也肯定会很有趣)。
编辑:我发现this issue要求完全相同的事情。
答案 0 :(得分:11)
使用Rust 1.0和1.1,您可以使用libc包来打印jemalloc统计信息:
#![feature(libc)]
extern crate libc;
use libc::*;
extern {fn je_malloc_stats_print (write_cb: extern fn (*const c_void, *const c_char), cbopaque: *const c_void, opts: *const c_char);}
extern fn write_cb (_: *const c_void, message: *const c_char) {
print! ("{}", String::from_utf8_lossy (unsafe {std::ffi::CStr::from_ptr (message as *const i8) .to_bytes()}));
}
fn main() {
unsafe {je_malloc_stats_print (write_cb, std::ptr::null(), std::ptr::null())};
}
在后来的Rust版本(1.8 - 1.14)中,我们将je_malloc_stats_print
重命名为je_stats_print
:
#![feature(libc)]
extern crate libc;
extern {fn je_stats_print (write_cb: extern fn (*const libc::c_void, *const libc::c_char), cbopaque: *const libc::c_void, opts: *const libc::c_char);}
extern fn write_cb (_: *const libc::c_void, message: *const libc::c_char) {
print! ("{}", String::from_utf8_lossy (unsafe {std::ffi::CStr::from_ptr (message as *const i8) .to_bytes()}));}
fn main() {unsafe {je_stats_print (write_cb, std::ptr::null(), std::ptr::null())};}
在单线程程序中,应该可以让您很好地测量结构占用的内存量。只需在创建结构之前和之后打印统计数据并计算差异。
您还可以使用Valgrind(Massif)来获取堆配置文件。它的工作方式与任何其他C程序一样。确保在可执行文件中启用了调试符号(例如,使用调试版本或自定义Cargo配置)。例如,您可以使用http://massiftool.sourceforge.net/来分析生成的堆配置文件。
(我在Debian Jessie上验证了这个,在不同的设置中你的里程可能会有所不同)。
为了在Valgrind中使用Rust,你可能需要switch to the system allocator:
#![feature(alloc_system)]
extern crate alloc_system;
jemalloc can be told转储内存配置文件。您可以使用Rust FFI执行此操作,但我没有调查此路线。
答案 1 :(得分:8)
就测量数据结构大小而言,通过使用特征和小编译器插件可以相当容易地完成。 Nicholas Nethercote在他的文章Measuring data structure sizes: Firefox (C++) vs. Servo (Rust)中展示了它在Servo中的运作方式;归结为将#[derive(HeapSizeOf)]
(或偶尔的手动实现)添加到您关心的每种类型。这是一种允许精确检查内存去向的好方法;然而,它是相对侵入性的,因为它需要首先进行更改,而jemalloc的print_stats()
之类的东西则不需要。尽管如此,对于良好和精确的测量,这是一种合理的方法。
答案 2 :(得分:6)
目前,获取分配信息的唯一方法是使用alloc::heap::stats_print();
方法(#![feature(alloc)]
后面),该方法调用jemalloc' print_stats()
。
一旦我了解了输出的含义,我就会用更多信息更新这个答案。
(请注意,我不接受这个答案,所以如果有人想出更好的解决方案......)
答案 3 :(得分:1)
现在有jemalloc_ctl
条板箱可提供方便的安全类型API 。将其添加到您的Cargo.toml
:
[dependencies]
jemalloc-ctl = "0.3"
jemallocator = "0.3"
然后将jemalloc
配置为global allocator并使用jemalloc_ctl::stats
模块中的方法:
这里是official example:
use std::thread;
use std::time::Duration;
use jemalloc_ctl::{stats, epoch};
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
fn main() {
loop {
// many statistics are cached and only updated when the epoch is advanced.
epoch::advance().unwrap();
let allocated = stats::allocated::read().unwrap();
let resident = stats::resident::read().unwrap();
println!("{} bytes allocated/{} bytes resident", allocated, resident);
thread::sleep(Duration::from_secs(10));
}
}