排查 Rust 中的内存泄漏方法 发表于 2025-03-04 | 分类于 编程 | 暂无评论 ## 问题描述 我们的前端灰度服务在每次发布之后,占用的内存会一直增长,最终耗尽所有内存从而导致 OOM。 内存泄漏的场景 - 循环引用:如果多个对象互相引用,导致它们无法被释放。 - 不正确地使用Box或Rc:这些类型可以用于管理内存,但如果使用不当,也会导致内存泄漏。 - 忘记释放资源:确保所有分配的内存,文件,网络连接等资源都得到了及时释放。 ## 排查工具 ### tokio-console PageServer 使用了 tokio 这个异步编程库。tokio-console 是一个用于审查 tokio 运行时的工具,可以帮助我们查看异步任务的运行状态。参考文档添加相关的代码来引入。开发者启动 tokio-console 命令便可以查看异步任务的状态了。 ```shell # 安装 & 引入相关初始化代码 cargo install --locked tokio-console # 默认链接端口为 6669 tokio-console http://127.0.0.1:5555 ``` ### jemalloc 既然没有出现异步任务的泄漏,那么接下来,只能去观察内存是如何分配的,那就必须要要使用到 jemalloc 了。需要在项目中引入这两个依赖: [tikv-jemallocato](https://crates.io/crates/tikv-jemallocator "tikv-jemallocato")r: 替换默认的内存分配器 [jemalloc_pprof](https://crates.io/crates/jemalloc_pprof "jemalloc_pprof"): 提供了导出 profile 文件的工具函数 将导出 profile 文件的逻辑包装成一个 http 接口,那么就可以运行过程中导出 profile 文件。在启动程序前,设置 export _RJEM_MALLOC_CONF=prof:true,lg_prof_interval:28 用以开启导出 profile 相关的功能。 jeprof 这款 cli 用来分析 profile 文件。当然也可以用 flamegraph.pl 来生成火焰图。 ```shell # 导出 profile 文件,并使用 jeprof 来分析 dump-profile() { curl http://127.0.0.1:3000/debug/profile/prof > "$1.prof" jeprof --svg ./target/release/page-server "$1.prof" > "$1.svg" # 导出成火焰图, flamegraph.pl 来自于 https://github.com/brendangregg/FlameGraph/blob/master/flamegraph.pl jeprof ./target/release/page-server "$1.prof" --collapse | perl flamegraph.pl > "$1.flamegraph.svg" } dump-profile 1 ``` ### k6 其实 k6 通常被当做压测工具来使用。不过借助它可以很方便的模拟出线上的请求。它的一个优点是可以通过 JavaScript 编写测试脚本。简单调整配置就可以模拟出线上的场景,对 前端 非常友好。 在安装完成了 k6 cli 后,使用 k6 new 生成测试脚本,执行 k6 run script.js 来执行测试。 ```shell import http from 'k6/http'; import { sleep } from 'k6'; export const options = { // 同时请求的数量 vus: 10, // 此次测试持续时长 duration: '30s', }; export default function () { const headers = { host: `some-project.huolala.cn`, timeout: '1s', }; http.get(`http://127.0.0.1:3001/${path}`, { headers }); sleep(1); } ``` ## 排查思路 1. 导出线上 profile 文件来分析 2. 使用 k6 来模拟线上请求,找出最小复现 demo 3. 定位问题所在,修复 bug ## 问题分析与解决 通过对 profile 文件的分析,我们发现有两处地方存在较高的内存占用。 转载自: >https://juejin.cn/post/7477767063705337883 有实际案例建议观看