gpt4 book ai didi

ruby-on-rails - Heroku Dyno 上的总内存上升

转载 作者:行者123 更新时间:2023-12-01 03:29:23 28 4
gpt4 key购买 nike

我有一个托管在 Heroku Dyno 上的网站,它允许最大 512MB 的内存。

我的网站允许用户上传 CSV 格式的原始时间序列数据,我想对上传约 100k 行(3.2 MB 大小)的 CSV 进行负载测试。 UI 允许用户上传文件,这反过来会启动 Sidekiq 作业,将文件中的每一行导入我的数据库。它将上传的文件存储在 /tmp 下测功机上的存储,我相信每次定期重新启动测功机时都会清除它。

一切实际上都没有错误地完成,并且插入了所有 100k 行。但几个小时后,我注意到我的网站几乎没有响应,于是我检查了 Heroku 指标。

在我开始上传的确切时间,内存使用量开始增长并迅速超过最大 512MB。

enter image description here

日志证实了这一事实——

# At the start of the job
Aug 22 14:45:51 gb-staging heroku/web.1: source=web.1 dyno=heroku.31750439.f813c7e7-0328-48f8-89d5-db79783b3024 sample#memory_total=412.68MB sample#memory_rss=398.33MB sample#memory_cache=14.36MB sample#memory_swap=0.00MB sample#memory_pgpgin=317194pages sample#memory_pgpgout=211547pages sample#memory_quota=512.00MB

# ~1 hour later
Aug 22 15:53:24 gb-staging heroku/web.1: source=web.1 dyno=heroku.31750439.f813c7e7-0328-48f8-89d5-db79783b3024 sample#memory_total=624.80MB sample#memory_rss=493.34MB sample#memory_cache=0.00MB sample#memory_swap=131.45MB sample#memory_pgpgin=441565pages sample#memory_pgpgout=315269pages sample#memory_quota=512.00MB
Aug 22 15:53:24 gb-staging heroku/web.1: Process running mem=624M(122.0%)

我可以重新启动 Dyno 来解决这个问题,但我在查看指标方面没有太多经验,所以我想了解发生了什么。
  • 如果我的工作在大约 30 分钟内完成,内存使用量可能会持续增长的一些常见原因是什么?在工作之前它相当稳定
  • 有没有办法告诉内存中存储了哪些数据?做一个内存转储会很棒,虽然我不知道它是否会超过十六进制地址数据
  • 我可以使用哪些其他工具来更好地了解情况?我可以通过上传另一个大文件来收集更多数据来重现这种情况

  • 只是有点迷失从哪里开始调查。

    谢谢!

    编辑: - 我们有 Heroku New Relic 插件,它也收集数据。令人讨厌的是,New Relic 报告了同一时间段内不同/正常的内存使用值。这很常见吗?它在测量什么?

    enter image description here

    最佳答案

    最可能的原因是:

    场景一 .您处理整个文件,首先将每条记录从 CSV 加载到内存,进行一些处理,然后对其进行迭代并存储到数据库中。

    如果是这种情况,那么您需要更改实现以批量处理此文件。加载 100 条记录,处理它们,存储在数据库中,重复。你也可以看看activerecord-import gem 来加快你的插入速度。

    场景二 .您的脚本中有内存泄漏。也许您分批处理,但您持有对未使用对象的引用,并且它们没有被垃圾收集。

    您可以使用 ObjectSpace模块。它有一些非常有用的方法。
    count_objects将返回带有当前在堆上创建的不同对象的计数的哈希:

    ObjectSpace.count_objects
    => {:TOTAL=>30162, :FREE=>11991, :T_OBJECT=>223, :T_CLASS=>884, :T_MODULE=>30, :T_FLOAT=>4, :T_STRING=>12747, :T_REGEXP=>165, :T_ARRAY=>1675, :T_HASH=>221, :T_STRUCT=>2, :T_BIGNUM=>2, :T_FILE=>5, :T_DATA=>1232, :T_MATCH=>105, :T_COMPLEX=>1, :T_NODE=>838, :T_ICLASS=>37}

    它只是一个哈希,因此您可以查找特定类型的对象:
    ObjectSpace.count_objects[:T_STRING]
    => 13089

    您可以将此片段插入脚本中的不同点,以查看特定时间堆上的对象数量。要获得一致的结果,您应该在检查计数之前手动触发垃圾收集器。它将确保您只能看到事件对象。
    GC.start
    ObjectSpace.count_objects[:T_STRING]

    另一个有用的方法是 each_object它迭代实际上在堆上的所有对象:
    ObjectSpace.each_object { |o| puts o.inspect }

    或者您可以迭代一个类的对象:
    ObjectSpace.each_object(String) { |o| puts o.inspect }

    场景三 .您在 gem 或系统库中存在内存泄漏。

    这与以前的情况类似,但问题不在于您的代码。您也可以使用 ObjectSpace 找到它。 .如果您看到调用库方法后保留了一些对象,则该库可能存在内存泄漏。解决方案是更新此类库。

    看看这个 repo .它维护具有已知内存泄漏问题的 gem 列表。如果您有此列表中的某些内容,我建议您快速更新它。

    现在解决您的其他问题。如果您在 Heroku 或任何其他提供商上拥有非常健康的应用程序,您将始终看到内存随着时间的推移而增加,但它应该会在某个时候稳定下来。 Heroku 大约每天重新启动一次 dynos。在您的指标上,您会看到在 2 天左右的时间内突然下降和缓慢增加。

    New Relic 默认显示所有实例的平均数据。您可能应该切换到仅显示来自工作人员测功机的数据,以查看正确的内存使用情况。

    最后推荐阅读 this article关于 Ruby 如何使用内存。那里提到了许多有用的工具, derailed_benchmarks尤其。它是由 Heroku 的人(当时)创建的,它是与人们在 Heroku 上遇到的最常见问题相关的许多基准的集合。

    关于ruby-on-rails - Heroku Dyno 上的总内存上升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39092704/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com