在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

記一次Rust內存泄漏排查之旅

jf_wN0SrCdH ? 來源:GreptimeDB ? 2023-07-02 11:52 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

在某次持續壓測過程中,我們發現 GreptimeDB 的 Frontend 節點內存即使在請求量平穩的階段也在持續上漲,直至被 OOM kill。我們判斷 Frontend 應該是有內存泄漏了,于是開啟了排查內存泄漏之旅。

Heap Profiling

大型項目幾乎不可能只通過看代碼就能找到內存泄漏的地方。所以我們首先要對程序的內存用量做統計分析。幸運的是,GreptimeDB 使用的 jemalloc 自帶 heap profiling[1],我們也支持了導出 jemalloc 的 profile dump 文件[2]。于是我們在 GreptimeDB 的 Frontend 節點內存達到 300MB 和 800MB 時,分別 dump 出了其內存 profile 文件,再用 jemalloc 自帶的jeprof分析兩者內存差異(--base參數),最后用火焰圖顯示出來:

d60c4194-1826-11ee-962d-dac502259ad0.png

顯然圖片中間那一大長塊就是不斷增長的 500MB 內存占用了。仔細觀察,居然有 thread 相關的 stack trace。難道是創建了太多線程?簡單用ps -T -p命令看了幾次 Frontend 節點的進程,線程數穩定在 84 個,而且都是預知的會創建的線程。所以“線程太多”這個原因可以排除。

再繼續往下看,我們發現了很多 Tokio runtime 相關的 stack trace,而 Tokio 的 task 泄漏也是常見的一種內存泄漏。這個時候我們就要祭出另一個神器:Tokio-console[3]。

Tokio Console

Tokio Console 是 Tokio 官方的診斷工具,輸出結果如下:

d644dd9c-1826-11ee-962d-dac502259ad0.png

我們看到居然有 5559 個正在運行的 task,且絕大多數都是 Idle 狀態!于是我們可以確定,內存泄漏發生在 Tokio 的 task 上。現在問題就變成了:GreptimeDB 的代碼里,哪里 spawn 了那么多的無法結束的 Tokio task?

從上圖的 "Location" 列我們可以看到 task 被 spawn 的地方[4]:

implRuntime{
///Spawn a future and execute it in this thread pool
///
///Similar to Tokio::spawn()
pubfnspawn(&self,future:F)->JoinHandle
where
F:Future+Send+'static,
F:Send+'static,
{
self.handle.spawn(future)
}
}

接下來的任務是找到 GreptimeDB 里所有調用這個方法的代碼。

..Default::default()

經過一番看代碼的仔細排查,我們終于定位到了 Tokio task 泄漏的地方,并在 PR #1512[5]中修復了這個泄漏。簡單地說,就是我們在某個會被經常創建的 struct 的構造方法中,spawn 了一個可以在后臺持續運行的 Tokio task,卻未能及時回收它。對于資源管理來說,在構造方法中創建 task 本身并不是問題,只要在Drop中能夠順利終止這個 task 即可。而我們的內存泄漏就壞在忽視了這個約定。

這個構造方法同時在該 struct 的Default::default()方法當中被調用了,更增加了我們找到根因的難度。

Rust 有一個很方便的,可以用另一個 struct 來構造自己 struct 的方法,即 "Struct Update Syntax"[6]。如果 struct 實現了Default,我們可以簡單地在 struct 的 field 構造中使用..Default::default()。

如果Default::default()內部有 “side effect”(比如我們本次內存泄漏的原因——創建了一個后臺運行的 Tokio task),一定要特別注意:struct 構造完成后,Default創建出來的臨時 struct 就被丟棄了,一定要做好資源回收

例如下面這個小例子:Rust Playground[7]

structA{
i:i32,
}

implDefaultforA{
fndefault()->Self{
println!("called A::default()");
A{i:42}
}
}

#[derive(Default)]
structB{
a:A,
i:i32,
}

implB{
fnnew(a:A)->Self{
B{
a,
//A::default()is called in B::default(),even though"a"is provided here.
..Default::default()
}
}
}

fnmain(){
leta=A{i:1};
letb=B::new(a);
println!("{}",b.a.i);
}

struct A 的default方法是會被調用的,打印出called A::default()。

總結

?排查 Rust 程序的內存泄漏,我們可以用 jemalloc 的 heap profiling 導出 dump 文件;再生成火焰圖可直觀展現內存使用情況。

? Tokio-console 可以方便地顯示出 Tokio runtime 的 task 運行情況;要特別注意不斷增長的 idle tasks。

?盡量不要在常用 struct 的構造方法中留下有副作用的代碼。

?Default只應該用于值類型 struct。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    8

    文章

    3115

    瀏覽量

    75091
  • 文件
    +關注

    關注

    1

    文章

    578

    瀏覽量

    25266
  • 線程
    +關注

    關注

    0

    文章

    507

    瀏覽量

    20119
  • Rust
    +關注

    關注

    1

    文章

    233

    瀏覽量

    7001

原文標題:記一次 Rust 內存泄漏排查之旅 | 經驗總結篇

文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    【freeRTOS開發筆記】一次坑爹的freeTOS升級

    【freeRTOS開發筆記】一次坑爹的freeTOS-v9.0.0升級到freeRTOS-v10.4.4
    的頭像 發表于 07-11 09:15 ?5190次閱讀
    【freeRTOS開發筆記】<b class='flag-5'>記</b><b class='flag-5'>一次</b>坑爹的freeTOS升級

    一次詭異的內存泄漏

    最近在補些基礎知識,恰好涉及到了智能指針std::weak_ptr在解決std::shared_ptr時候循環引用的問題
    的頭像 發表于 02-19 13:44 ?903次閱讀
    <b class='flag-5'>記</b><b class='flag-5'>一次</b>詭異的<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>

    一次網站設計稿的方法

    一次網站設計稿
    發表于 06-16 09:43

    寫了內存泄漏檢查工具

    嵌入式環境內存泄漏檢查比較麻煩,valgrind比較適合于在pc上跑,嵌入式上首先移植就很麻煩,移植完了內存比較小,跑起來也比較費勁。所以手動寫了
    發表于 12-17 08:25

    分享內存泄漏定位排查技巧

    的調試工具,下面分享內存泄漏定位排查技巧。1.對malloc,free進行封裝首先,我們對malloc,f
    發表于 12-17 08:13

    sqlite軟件包內存泄漏如何解決?

    內存泄漏到底是我應用程序的問題還是軟件包本身的問題,該怎么排查呢?硬件使用的nuc980dk61ycvoid app_sqlite3_thread(void *argument){ sqlite3_initialize(); s
    發表于 05-24 15:25

    嵌入式裝置內存泄漏檢測系統設計

    ,極易出現應用程序內存泄漏內存泄漏按照發生的頻率可分為常發性、偶發性、一次性以及隱式內存
    發表于 04-26 14:35 ?3次下載
    嵌入式裝置<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>檢測系統設計

    如何處理服務存在內存泄漏問題?

    上周像往常樣例行檢查線上機器性能,突然發現個服務的內存使用率是這樣的: 很顯然該服務存在內存泄漏問題,趕緊
    的頭像 發表于 03-02 10:23 ?2315次閱讀

    一次性輸液器泄漏正負壓檢測儀

    一次性輸液器泄漏正負壓測試儀是根據《GB8368-2018一次性使用輸液器 重力輸液式》中的相關條款設計研發制造的,是款專業用于檢測一次
    發表于 01-28 16:44 ?999次閱讀
    <b class='flag-5'>一次</b>性輸液器<b class='flag-5'>泄漏</b>正負壓檢測儀

    一次性輸液器泄漏正負壓檢測儀

    一次性輸液器泄漏正負壓測試儀是根據《GB8368-2018一次性使用輸液器 重力輸液式》中的相關條款設計研發制造的,是款專業用于檢測一次
    的頭像 發表于 01-29 15:30 ?1403次閱讀
    <b class='flag-5'>一次</b>性輸液器<b class='flag-5'>泄漏</b>正負壓檢測儀

    glibc導致的堆外內存泄露的排查過程

    本文記錄一次glibc導致的堆外內存泄露的排查過程。
    的頭像 發表于 09-01 09:43 ?999次閱讀
    glibc導致的堆外<b class='flag-5'>內存</b>泄露的<b class='flag-5'>排查</b>過程

    什么是內存泄漏?如何避免JavaScript內存泄漏

    JavaScript 代碼中常見的內存泄漏的常見來源: 研究內存泄漏問題就相當于尋找符合垃圾回收機制的編程方式,有效避免對象引用的問題。
    發表于 10-27 11:30 ?636次閱讀
    什么是<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>?如何避免JavaScript<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>

    內存泄漏如何避免

    的數,那就是內存溢出。 2. 內存泄漏 內存泄露 memory leak,是指程序在申請內存后,無法釋放已申請的
    的頭像 發表于 11-10 11:04 ?1025次閱讀
    <b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>如何避免

    線程內存泄漏問題的定位

    記錄個關于線程內存泄漏問題的定位過程,以及過程中的收獲。 1. 初步定位 是否存在內存泄漏:想到內存
    的頭像 發表于 11-13 11:38 ?844次閱讀
    線程<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>問題的定位

    一次Rust重寫基礎軟件的實踐

    受到2022年“谷歌使用Rust重寫Android系統且所有Rust代碼的內存安全漏洞為零” [1] 的啟發,最近筆者懷著濃厚的興趣也順應Rust 的潮流,嘗試著將
    的頭像 發表于 01-25 11:21 ?937次閱讀
    主站蜘蛛池模板: 曰韩一级 | 加勒比黑人喝羽月希奶水 | 五月婷婷精品 | 女人张腿让男桶免费视频网站 | 四虎884tt紧急大通知 | 免费高清在线观看a网站 | 一级aaaaaa片毛片在线播放 | 四虎h789fcom | 久久久久久免费播放一级毛片 | 一级女人毛片人一女人 | 天天看片夜夜爽 | 日日操夜夜骑 | 99久久国产综合精品国 | 电源天堂 | 欧美高清milf在线播放 | 丁香婷婷色 | 圆胖肥女人性视频 | 人人干人人做 | 欧美一级特黄乱妇高清视频 | 天天摸天天添人人澡 | 国产精品久久久久免费 | 天天做夜夜做 | 亚洲夜夜操 | 亚洲视频在线网 | 日本三级全黄 | 免费看黄的视频软件 | 欧美xxxx色视频在线观看 | 五月亭亭激情五月 | 久久成人国产精品免费 | 欧美福利二区 | 日本不卡视频一区二区 | 色88888久久久久久影院 | 天堂资源吧 | 免费看逼网站 | 亚洲一区 在线播放 | 欧美ol丝袜高跟秘书在线播放 | 日日操天天操夜夜操 | 福利视频一区二区牛牛 | 国产婷婷综合在线精品尤物 | 国产三级视频在线播放 | 天天天干干干 |