繁体   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