使用jeprof分析rust的内存
文章目录
配置项目使用Jemalloc内存分配器
声明Cargo.toml
依赖
[dependencies]
jemallocator = { version = "0.5.0", features = ["debug","profiling"] }
jemalloc-sys = { version = "0.5.1+5.3.0-patched", features = ["debug","profiling"] }
声明使用全局内存分配器
#[global_allocator]
static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
fn main() {
// do
}
声明定时任务导出heap文件
use jemalloc_sys::mallctl;
use std::os::raw::{c_char, c_int};
use std::ptr;
use std::thread::sleep;
use std::time::Duration;
pub fn spawn_dump() {
let thread = std::thread::Builder::new().name("spawn_dump".to_owned());
thread
.spawn(|| loop {
let r = dump();
println!("---------------dump ret: {} -------------------", r);
sleep(Duration::from_secs(10));
})
.unwrap();
}
fn dump() -> c_int {
unsafe {
mallctl(
"prof.dump\0".as_bytes() as *const _ as *const c_char,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
0,
)
}
}
生成prof文件
导环境变量_RJEM_MALLOC_CONF,开启prof
export _RJEM_MALLOC_CONF="prof:true,prof_prefix:/tmp/jeprof.out"
运行程序
./target/release/test-dump
prof_prefix目录下查看对应的转储文件
root@DESKTOP:/mnt/d/Code/Test/test-utils# ls /tmp/ -l
total 24
-rw-r--r-- 1 root root 10617 Jul 8 16:33 jeprof.out.10444.0.m0.heap
-rw-r--r-- 1 root root 11057 Jul 8 16:33 jeprof.out.10444.1.m1.heap
使用jeprof 分析
更多的jeprof使用可以直接查看官方文档
输出文本
执行命令
jeprof --text ./target/release/test-dump --base /tmp/jeprof.out.10444.0.m0.heap /tmp/jeprof.out.10444.1.m1.heap
结果:
Total: 49.6 MB
49.6 100.0% 100.0% 49.6 100.0% prof_backtrace_impl
0.0 0.0% 100.0% 50.1 101.0% ::call_once (inline)
0.0 0.0% 100.0% 50.1 101.0% _ZN3std10sys_common9backtrace28__rust_begin_short_backtrace17ha86af95e1f7ae42bE.llvm.3306111440337745050
0.0 0.0% 100.0% -0.5 -1.0% _ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17ha669e04e9178e70eE.llvm.9294924536515583548
0.0 0.0% 100.0% -0.5 -1.0% __libc_start_main
0.0 0.0% 100.0% 49.6 100.0% _rjem_je_malloc_default
0.0 0.0% 100.0% 49.6 100.0% _rjem_je_prof_backtrace
0.0 0.0% 100.0% 49.6 100.0% _rjem_je_prof_tctx_create
0.0 0.0% 100.0% -0.5 -1.0% _start
0.0 0.0% 100.0% 50.1 101.0% clone
0.0 0.0% 100.0% 50.1 101.0% core::ops::function::FnOnce::call_once{{vtable-shim}}
0.0 0.0% 100.0% -0.5 -1.0% core::ops::function::impls::::call_once (inline)
0.0 0.0% 100.0% 49.6 100.0% imalloc_body
0.0 0.0% 100.0% -0.5 -1.0% main
0.0 0.0% 100.0% 49.6 100.0% prof_alloc_prep (inline)
0.0 0.0% 100.0% 50.1 101.0% start_thread
0.0 0.0% 100.0% -0.5 -1.0% std::panic::catch_unwind (inline)
0.0 0.0% 100.0% -0.5 -1.0% std::panicking::try (inline)
0.0 0.0% 100.0% -0.5 -1.0% std::panicking::try::do_call (inline)
0.0 0.0% 100.0% -0.5 -1.0% std::rt::lang_start_internal
0.0 0.0% 100.0% -0.5 -1.0% std::rt::lang_start_internal::{{closure}} (inline)
0.0 0.0% 100.0% 50.1 101.0% std::sys::unix::thread::Thread::new::thread_start
0.0 0.0% 100.0% -0.5 -1.0% std::sys_common::backtrace::__rust_begin_short_backtrace
0.0 0.0% 100.0% -0.5 -1.0% test_dump::main
0.0 0.0% 100.0% 49.6 100.0% test_dump::random_memory
输出dot 图
执行命令
jeprof --dot ./target/release/test-dump --base /tmp/jeprof.out.10444.0.m0.heap /tmp/jeprof.out.10444.1.m1.heap
将生成的dot复制到http://www.webgraphviz.com/ 上生成图片
digraph "./target/release/test-dump; 49.6 MB" {
node [width=0.375,height=0.25];
Legend [shape=box,fontsize=24,shape=plaintext,label="./target/release/test-dump\lTotal MB: 49.6\lFocusing on: 49.6\lDropped nodes with <= 0.2 abs(MB)\lDropped edges with <= 0.0 MB\l"];
N1 [label="\ncall_once\n(inline)\n0.0 (0.0%)\rof 50.1 (101.0%)\r",shape=box,fontsize=8.0];
N2 [label="_ZN3std10sys_common9backtrace28__rust_begin_short_backtrace17ha86af95e1f7ae42bE.llvm.3306111440337745050\n0.0 (0.0%)\rof 50.1 (101.0%)\r",shape=box,fontsize=8.0];
N3 [label="clone\n0.0 (0.0%)\rof 50.1 (101.0%)\r",shape=box,fontsize=8.0];
N4 [label="core\nops\nfunction\nFnOnce\ncall_once{{vtable-shim}}\n0.0 (0.0%)\rof 50.1 (101.0%)\r",shape=box,fontsize=8.0];
N5 [label="start_thread\n0.0 (0.0%)\rof 50.1 (101.0%)\r",shape=box,fontsize=8.0];
N6 [label="std\nsys\nunix\nthread\nThread\nnew\nthread_start\n0.0 (0.0%)\rof 50.1 (101.0%)\r",shape=box,fontsize=8.0];
N7 [label="_rjem_je_malloc_default\n0.0 (0.0%)\rof 49.6 (100.0%)\r",shape=box,fontsize=8.0];
N8 [label="_rjem_je_prof_backtrace\n0.0 (0.0%)\rof 49.6 (100.0%)\r",shape=box,fontsize=8.0];
N9 [label="_rjem_je_prof_tctx_create\n0.0 (0.0%)\rof 49.6 (100.0%)\r",shape=box,fontsize=8.0];
N10 [label="imalloc_body\n0.0 (0.0%)\rof 49.6 (100.0%)\r",shape=box,fontsize=8.0];
N11 [label="prof_alloc_prep\n(inline)\n0.0 (0.0%)\rof 49.6 (100.0%)\r",shape=box,fontsize=8.0];
N12 [label="prof_backtrace_impl\n49.6 (100.0%)\r",shape=box,fontsize=58.0];
N13 [label="test_dump\nrandom_memory\n0.0 (0.0%)\rof 49.6 (100.0%)\r",shape=box,fontsize=8.0];
N14 [label="_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17ha669e04e9178e70eE.llvm.9294924536515583548\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N15 [label="__libc_start_main\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N16 [label="_start\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N17 [label="core\nops\nfunction\nimpls\n\ncall_once\n(inline)\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N18 [label="main\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N19 [label="std\npanic\ncatch_unwind\n(inline)\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N20 [label="std\npanicking\ntry\n(inline)\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N21 [label="std\npanicking\ntry\ndo_call\n(inline)\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N22 [label="std\nrt\nlang_start_internal\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N23 [label="std\nrt\nlang_start_internal\n{{closure}}\n(inline)\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N24 [label="std\nsys_common\nbacktrace\n__rust_begin_short_backtrace\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N25 [label="test_dump\nmain\n0.0 (0.0%)\rof -0.5 (-1.0%)\r",shape=box,fontsize=8.0];
N6 -> N1 [label=50.1, weight=100000, style="setlinewidth(2.000000),dashed"];
N1 -> N1 [label=50.1, weight=100000, style="setlinewidth(2.000000),dashed"];
N4 -> N2 [label=50.1, weight=100000, style="setlinewidth(2.000000)"];
N1 -> N4 [label=50.1, weight=100000, style="setlinewidth(2.000000)"];
N2 -> N13 [label=50.1, weight=100000, style="setlinewidth(2.000000)"];
N5 -> N6 [label=50.1, weight=100000, style="setlinewidth(2.000000)"];
N3 -> N5 [label=50.1, weight=100000, style="setlinewidth(2.000000)"];
N7 -> N10 [label=49.6, weight=100000, style="setlinewidth(2.000000)"];
N10 -> N11 [label=49.6, weight=100000, style="setlinewidth(2.000000),dashed"];
N13 -> N7 [label=49.6, weight=100000, style="setlinewidth(2.000000)"];
N11 -> N9 [label=49.6, weight=100000, style="setlinewidth(2.000000)"];
N8 -> N12 [label=49.6, weight=100000, style="setlinewidth(2.000000)"];
N11 -> N11 [label=49.6, weight=100000, style="setlinewidth(2.000000),dashed"];
N9 -> N8 [label=49.6, weight=100000, style="setlinewidth(2.000000)"];
N23 -> N19 [label=-0.5, weight=9944, style="setlinewidth(0.059270),dashed"];
N18 -> N22 [label=-0.5, weight=9944, style="setlinewidth(0.059270)"];
N16 -> N15 [label=-0.5, weight=9944, style="setlinewidth(0.059270)"];
N21 -> N17 [label=-0.5, weight=9944, style="setlinewidth(0.059270),dashed"];
N24 -> N25 [label=-0.5, weight=9944, style="setlinewidth(0.059270)"];
N14 -> N24 [label=-0.5, weight=9944, style="setlinewidth(0.059270)"];
N25 -> N13 [label=-0.5, weight=9944, style="setlinewidth(0.059270)"];
N17 -> N14 [label=-0.5, weight=9944, style="setlinewidth(0.059270)"];
N22 -> N19 [label=-0.5, weight=9944, style="setlinewidth(0.059270),dashed"];
N21 -> N23 [label=-0.5, weight=9944, style="setlinewidth(0.059270),dashed"];
N15 -> N18 [label=-0.5, weight=9944, style="setlinewidth(0.059270)"];
N20 -> N21 [label=-1.0, weight=16155, style="setlinewidth(0.118540),dashed"];
N19 -> N20 [label=-1.0, weight=16155, style="setlinewidth(0.118540),dashed"];
}
TODO
出现内存地址:可以使用gdb的info symbol 0x0000555555574dc3 方式确定内存地址对应的函数信息
https://github.com/tikv/jemallocator/issues/33