Ruby内存使用量失控。

4
我从一家数据供应商那里使用RestClient下载了大约75张图片和40页详细信息。
步骤如下:
  1. 验证供应商服务并将Cookie保存在变量中
  2. 下载XML文件
  3. XML文件包含大约40个资产。
  4. 对于每个资产,下载图像列表。(每个资产的图像数量在0-10之间)
  5. 下载图像。
我的总下载大小为148.14Mb,在37.58秒内通过115个唯一请求完成。我的内存消耗是:
Total allocated: 1165532095 bytes (295682 objects)
Total retained:  43483 bytes (212 objects)

使用memory_profiler gem测量。下载大约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

谢谢


这是我的示例代码:https://gist.github.com/mtrolle/96f55822122ecabd3cc46190a6dc18a5 - mtrolle
当你说“一个任务”时,你指的是什么?Rake 任务?Active Job? - Anthony
实际上只运行一次。通常我会通过Rails的ActiveJob执行此操作,但我正在使用上面链接的独立文件复制内存问题。如上所述,当检索15天数据中的1天时,每多解析一天,内存消耗呈指数级增长。 - mtrolle
你没有指定Ruby版本、主机操作系统或正在解析的资源。此外,你也没有提供完整的代码。(除非你将图像下载到内存中,然后在没有进一步处理的情况下将它们丢弃)所以我唯一能给出的建议是:不要使用RestClient,因为它已经超过一年没有更新了。使用更常用的东西,比如httparty - anothermh
我认为我们还没有证明RestClient是问题所在,但我同意,版本和平台会很有帮助。 - Anthony
显示剩余3条评论
1个回答

3
我认为这与您正在使用的http客户端有关:Rest-Client。不幸的是,它有一些被认为是占用内存过多的坏名声。您应该寻找一些既内存/时间高效的很棒的gem。

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

对于一个很好的基准,请看下面这篇由另一个伟大的gemShrine的作者写的文章:https://twin.github.io/httprb-is-great/

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

版本: 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)

相较于使用Rest-Client下载约1GB,该程序仅分配了7MB的内存来下载96.92MB。

以下是代码片段:https://gist.github.com/mtrolle/96f55822122ecabd3cc46190a6dc18a5#gistcomment-2774405


1
不错,Wasif兄弟! - K M Rakibul Islam
非常欢迎!很高兴能够分享这些很棒的宝石 :) - Wasif Hossain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接