如何使用jeprof分析rust的内存

使用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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Rust内存管理优势主要体现在以下几个方面: 1. 零成本抽象:Rust提供了诸多高级抽象特性,如所有权系统、借用检查器和生命周期等,但这些抽象在运行时几乎没有额外的开销。这意味着Rust可以在保证安全性的同时,避免了传统垃圾回收机制引入的运行时开销。 2. 所有权系统:Rust的核心特性之一就是所有权系统。通过所有权系统,Rust确保每块内存只有一个所有者,并且在编译时进行静态检查,避免了数据竞争和内存错误。这使得Rust能够在编译时捕获内存安全问题,而不需要运行时的垃圾回收或引用计数。 3. 借用检查器:Rust的借用检查器确保了对数据的访问是安全和有效的。它通过引入借用规则和生命周期来确保内存的正确使用。借用检查器在编译时检查借用关系,并防止数据竞争和悬垂指针等常见错误。 4. 内存安全性:Rust在编译时保证了内存安全性,避免了常见的内存错误,如空指针引用、野指针访问和缓冲区溢出等。这使得Rust能够提供更高的代码可靠性和稳定性,减少了潜在的安全漏洞。 总体而言,Rust内存管理优势在于其强大而高效的所有权系统和借用检查器,能够在编译时捕获内存错误,并保证内存安全性,同时避免了传统垃圾回收机制引入的运行时开销。这使得Rust成为一种适用于系统级编程和高性能应用的语言选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值