首页 > 解决方案 > Ruby 内存使用变得疯狂

问题描述

我从一个数据供应商那里下载了大约 75 张图片 + 40 页的详细信息,我使用 RestClient 完成了一项工作。

像这样:

  1. 向供应商服务进行身份验证并在变量中设置 cookie jar
  2. 下载 XML
  3. XML 包含大约 40 个资产。
  4. 对于图像的每个资产下载列表。(每个资产包含 0-10 张图片)。
  5. 下载图片。

通过 115 个唯一请求,我在 37.58 秒内的总下载大小为 148.14Mb。我的内存消耗是:

Total allocated: 1165532095 bytes (295682 objects)
Total retained:  43483 bytes (212 objects)

memory_profiler宝石测量。下载大约 150mb 的数据需要 1gb 以上的内存?

我最担心的是,我需要下载更多数据——这只是 15 天数据中的 1 天。当我运行 2 天的数据时,我将下载大小和内存大小加倍。当运行 3 天的数据时,我增加了三倍等。它甚至看起来内存消耗呈指数增长,直到我用完内存并且我的服务器崩溃。

为什么垃圾收集在这里没有发挥作用?我已经尝试GC.start在我下载的每一天的数据之间运行,这是技巧memory_profiler,但是当我添加太多天的数据时,我的服务器仍然最终崩溃。

所以我的问题是:

  1. 与我实际下载的数据相比,为什么内存消耗如此之高。
  2. 当我在每次下载之间覆盖保存下载数据的变量时,垃圾收集是否应该不清除以前数据下载的内存?
  3. 有什么技巧可以降低内存消耗?

版本: Ruby:2.4.4p296,RestClient:2.0.2,操作系统:Ubuntu 16.04

示例代码:

使用 RestClient:https ://gist.github.com/mtrolle/96f55822122ecabd3cc46190a6dc18a5

使用 HTTParty:https ://gist.github.com/mtrolle/dbd2cdf70f77a83b4178971aa79b6292

谢谢

标签: rubymemory-managementrest-client

解决方案


我相信这与您正在使用的 http 客户端有关:Rest-Client. 不幸的是,它有一些内存饥渴的坏名声。您绝对应该寻找一些既节省内存又节省时间的出色宝石。

我强烈推荐HTTP.rb或其 http/2 的继任者HTTPX

要获得一个好的基准,请查看另一个很棒的 gem Shrine的作者的这篇很棒的文章:https ://twin.github.io/httprb-is-great/

这是我在本地机器上用 HTTP.rb 替换 Rest-Client 后发现的:

版本:Ruby:2.5.3p105,HTTP.rb:4.0.0,操作系统:Ubuntu 16.04

总下载大小:96.92Mb ,包含118 个唯一请求。

内存消耗:

Total allocated: 7107283 bytes (83437 objects)
Total retained:  44221 bytes (385 objects)

因此它在下载96.92Mb时仅分配了7Mb ,而使用 Rest-Client 大约为 1Gb。

这是片段:https ://gist.github.com/mtrolle/96f55822122ecabd3cc46190a6dc18a5#gistcomment-2774405


推荐阅读