记一次性Rust内存走漏排查之旅 (记一次性游戏)
在某次继续压测环节中,咱们发现GreptimeDB的Frontend节点内存即使在恳求量颠簸的阶段也在继续下跌,直至被OOMkill。咱们判别Frontend应该是有内存走漏了,于是开启了排查内存走漏之旅。
HeapProfiling
大型名目简直无法能只经过看代码就能找到内存走漏的中央。所以咱们 首先要对程序的内存用量做统计剖析 。幸运的是,GreptimeDB经常使用的jemalloc自带heapprofiling[1],咱们也允许了导出jemalloc的profiledump文件[2]。于是咱们在GreptimeDB的Frontend节点内存到达300MB和800MB时,区分dump出了其内存profile文件,再用jemalloc自带的jeprof剖析两者内存差异(--base参数),最后用火焰图显示进去:
显然图片两边那一大长块就是始终增长的500MB内存占用了。细心观察,居然有thread关系的stacktrace。难道是创立了太多线程?繁难用ps-T-p命令看了几次Frontend节点的进程,线程数稳固在84个,而且都是预知的会创立的线程。所以线程太多这个要素可以扫除。
再继续往下看,咱们发现了很多Tokioruntime关系的stacktrace,而Tokio的task走漏也是经常出现的一种内存走漏。这个时刻咱们就要祭出另一个神器:Tokio-console[3]。
TokioConsole
TokioConsole是Tokio官网的诊断工具,输入结果如下:
咱们看到 居然有5559个正在运转的task,且绝大少数都是Idle形态!于是咱们可以确定,内存走漏出当初Tokio的task上 。如今疑问就变成了:GreptimeDB的代码里,哪里spawn了那么多的无法完结的Tokiotask?
从上图的"Location"列咱们可以看到task被spawn的中央[4]:
implRuntime{
///Spawnafutureandexecuteitinthisthreadpool
///SimilartoTokio::runtime::Runtime::spawn
pubfnspawn<F>(&self,future:F)->JoinHandle<F::Output>
F:Future+Send+'static,
F::Output:Send+'static,
self.handle.spawn(future)
接上去的义务是找到GreptimeDB里一切调用这个方法的代码。
..Default::default
经过一番看代码的细心排查,咱们终于定位到了Tokiotask走漏的中央,并在PR#1512[5]中修复了这个走漏。繁难地说,就是咱们在 某个会被经常创立的struct的结构方法中,spawn了一个可以在后盾继续运转的Tokiotask,却未能及时回收它 。关于资源治理来说,在结构方法中创立task自身并不是疑问,只需在Drop中能够顺利中断这个task即可。而咱们的内存走漏就坏在漠视了这个商定。
这个结构方法同时在该struct的Default::default方法当中被调用了,更参与了咱们找到根因的难度。
有一个很繁难的,可以用另一个struct来结构自己struct的方法,即"StructUpdateSyntax"[6]。假设struct成功了Default,咱们可以繁难地在struct的field结构中经常使用..Default::default。
假设Default::default外部有sideeffect(比如咱们本次内存走漏的要素——创立了一个后盾运转的Tokiotask),必定要特意留意: struct结构成功后, Default 创立进去的暂时struct就被摈弃了,必定要做好资源回收
例如上方这个小例子:RustPlayground[7]
implDefaultforA{
fndefault->Self{
println!("calledA::default");
#[derive(Default)]
fnnew(a:A)->Self{
//A::defaultiscalledinB::default,eventhough"a"isprovidedhere.
..Default::default
leta=A{i:1};
letb=B::new(a);
println!("{}",b.a.i);
structA的default方法是会被调用的,打印出calledA::default。
总结
•排查Rust程序的内存走漏,咱们可以用jemalloc的heapprofiling导出dump文件;再生成火焰图可直观展现内存经常使用状况。
•Tokio-console可以繁难地显示出Tokioruntime的task运转状况;要特意留意始终增长的idletasks。
•尽量不要在罕用struct的结构方法中留下有反作用的代码。
•Default只应该用于值类型struct。
参考
[1]
[2]
[3]
[4]
[5]
[6]
[7]
2GB内存能玩rust吗
这个游戏要求电脑内存达到最低4GB,推荐达到8GB内存。
楼主电脑只有2GB内存,明显是低了,建议考虑升级内存之后再玩,比较流畅。
如有不懂之处请追问,有帮助请采纳,谢谢.
rust内存小于10g怎么办
内存不足重开机就释放了,再说10g的内存那是很大了,好多新机器内存都只8g,足够你用了
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。