簡體   English   中英

如何分析 ruby on rails memory 泄漏?

[英]How to analyze ruby on rails memory leak?

我正在處理一個遺留系統(Ruby 2.7.6),它存在 memory 泄漏,導致以前的開發人員使用puma worker killer通過每 30 分鍾重新啟動進程來克服 memory 問題。 隨着流量的增加,我們現在需要增加實例數量並將 30 分鍾的殺死率降低到甚至 20 分鍾。

我們想調查這個 memory 泄漏的來源,它顯然源自我們的許多 Gem 依賴項之一(以前的開發人員提供的信息)。

該系統在 AWS(Elastic Beanstalk)上,但也可以在 docker 上運行。任何人都可以建議一個好的工具並指導如何找到這個 memory 泄漏的來源嗎? 謝謝

** 更新:我使用了mini-profiler並拍攝了一些 memory 快照以查看服務器上大約 100 個請求的影響,[之前、期間、之后]

從輸出來看,似乎 Ruby 中沒有 memory 泄漏,但 memory 的使用確實增加並保持不變,盡管我們似乎沒有使用...

之前

KiB Mem:總計 2007248,免費 628156,已使用 766956,612136 buff/緩存 KiB 交換:總計 2097148,免費 2049276,已使用 47872。 1064852 可用內存

總分配:115227 字節(1433 個對象)總保留:21036 字節(147 個對象)

由 gem 分配 memory

 33121 activesupport-6.0.4.7 21687 actionpack-6.0.4.7 14484 activerecord-6.0.4.7 12582 var/app 9904 ipaddr 6957 rack-2.2.4 3512 actionview-6.0.4.7 2680 mysql2-0.5.3 1813 rack-mini-profiler-3.0.0 1696 audited-5.0.2 1552 concurrent-ruby-1.1.10

期間

KiB Mem:總計 2007248,免費 65068,已使用 1800424,141756 buff/緩存 KiB 交換:總計 2097148,免費 2047228,已使用 49920。
58376 可用內存

總分配:225272583 字節(942506 個對象)總保留:1732241 字節(12035 個對象)

由 gem 分配 memory

106497060 maxmind-db-1.0.0
58308032 心理
38857594 user_agent_parser-2.7.0
4949108 activesupport-6.0.4.7
3967930 其他
3229962 activerecord-6.0.4.7
2154670 機架 2.2.4
1467383 動作包-6.0.4.7
1336204 activemodel-6.0.4.7

后:

KiB Mem:總計 2007248,免費 73760,已使用 1817688,115800 buff/緩存 KiB 交換:總計 2097148,免費 2032636,已使用 64512。
54448 可用內存

總分配:109563 字節(1398 個對象)總保留:14988 字節(110 個對象)

由 gem 分配 memory

 29745 activesupport-6.0.4.7 21495 actionpack-6.0.4.7 13452 activerecord-6.0.4.7 12502 var/app 9904 ipaddr 7237 rack-2.2.4 3128 actionview-6.0.4.7 2488 mysql2-0.5.3 1813 rack-mini-profiler-3.0.0 1360 audited-5.0.2 1360 concurrent-ruby-1.1.10

那么泄漏在哪里? 是彪馬嗎?

從問題的統計數據來看,大多數對象都被 memory 分配器正確釋放了。

但是 - 當您有很多重復分配時,系統的malloc有時(並且經常)持有 memory 而不將其釋放給系統。

這樣做有兩個主要原因:

  1. 最重要的是: 堆碎片(分配器無法釋放 memory 並且無法將其部分用於未來的分配)。

  2. 系統的 memory 分配器知道它可能很快會再次需要這個 memory(這與 memory 中可以釋放且不會出現碎片的部分有關)。

這可以通過嘗試將系統的 memory 分配器替換為針對您的特定需求調整的分配器來解決(即jamalloc ,如建議的herehere以及詢問here )。

在使用 C 擴展時,您還可以嘗試使用具有自定義 memory 分配器的 gem( iodine gem 會這樣做,但您也可以讓其他 gem 這樣做)。

這種方法應該有助於緩解這個問題,但事實是你的一些寶石看起來 memory 餓了......我的意思是......:

  • maxmind-db gem 是使用 memory 的 106,497,060 字節 (106MB) 還是分配了那么多對象?

  • 為什么psych如此飢餓? data 和 YAML 之間是否有任何可以跳過的往返?

  • 似乎同時存儲了很多用戶代理字符串......( user_agent_parser gem)......也許你可以緩存這些字符串而不是有很多重復項。 例如,您可以將這些字符串組成一個Set ,並將集合中的每個字符串 object 替換為 object。 這樣,相等的字符串將指向相同的 object(防止某些 object 重復並釋放一些內存)。

是彪馬嗎?

可能不會。

雖然我是iodine web 服務器的作者,但我真的很喜歡 Puma 團隊多年來所做的工作,並認為它是一個超級可靠的服務器。 我真的懷疑泄漏來自服務器,但您可以隨時切換並查看會發生什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM