ruby-on-rails - Rails 应用程序中的内存不断增加

标签 ruby-on-rails memory heroku

我最近推出了一个新的 Ruby on Rails 应用程序,它在开发模式下运行良好。启动后我一直在体验内存使用量不断增加:

Screen dump from New Relic, Dyno memory usage

UPDATED: When this screen dump from New Relic was taken. I have scheduled a web dyno restart every hour (one out of two web dynos). Thus, it does not reach the 500Mb-crash level and it actually gets a bit of a sig saw pattern. The problem is not at all resolved by this though, only some of the symptoms. As you can see the morning is not so busy but the afternoon is more busy.

更新:当这张来自 New Relic 的屏幕转储(下一个)被拍摄时。我已经安排了每小时重新启动一次网络测功机(两个网络测功机中的一个)。因此,它没有达到 500Mb 的崩溃级别,实际上它有点像锯齿状图案。这个问题根本没有解决,只是一些症状。如您所见,早上并不那么忙,但下午更忙。我在 11.30 上传了一个小细节,即使它出现在统计数据中,它也不会影响问题。

还可以注意到,即使图表显示 AVG 内存,MIN 内存仍在不断增加。即使图表似乎在图表中暂时下降,最小内存保持不变或增加。 MIN 内存永远不会减少!

应用程序将(无需重新启动测功机)增加内存,直到达到 Heroku 的最大级别,并且应用程序因执行过期类型的错误而崩溃。

我不是一个优秀的程序员,但我之前做过一些应用程序,没有遇到过这类问题。

已进行故障排除

A.我认为问题出在 application_controller ( Will variables in application controller cause a memory leak in Rails? ) 中的 before_filter 中,但这不是问题。

B.我安装了 oink 但它没有给出任何结果(根本)。它会创建一个 oink.log,但在我运行“heroku run oink -m log/oink.log”时不会给出任何结果,无论阈值是多少。

C.我尝试了 bleak_house,但它已被弃用,无法安装

D.我已经在 Google 上搜索并阅读了该主题中的大多数文章,但我并不聪明。

E.我很想测试 memprof 但我无法安装它(我有 Ruby 1.9x 并且真的不知道如何将它降级到 1.8x)

我的问题:

第一季度。我真正想知道的是每个请求都在增加的变量的名称,或者至少是哪个 Controller 使用的内存最多。

第二季度。下面代码中的 Controller 会增加内存吗?

related_feed_categories = []
@gift.tags.each do |tag|
  tag.category_connections.each do |cc|
    related_feed_categories << cc.category_from_feed
  end
end

(抱歉,出于某种原因,SO 不会重新格式化代码以使其易于阅读)。

之后我是否需要用“related_feed_categories = nil”来“杀死”related_feed_categories,还是垃圾收集器会处理这个问题?

第三季度。我要寻找的主要内容是什么?现在我根本无法缩小范围。我不知道要深入查看代码的哪一部分,也不知道要查找什么。

第四季度。万一我真的解决不了问题。是否有任何在线咨询服务可以发送我的代码并让他们找到问题?

谢谢!

更新。收到评论后,它可能与 session 有关。这是我猜可能不好的部分代码:

# Create sessions for last generation
friend_data_arr = [@generator.age, @generator.price_low, @generator.price_high]
friend_positive_tags_arr = []
friend_negative_tags_arr = []
friend_positive_tags_arr << @positive_tags
friend_negative_tags_arr << @negative_tags    
session["last_generator"] = [friend_data_arr, friend_positive_tags_arr, friend_negative_tags_arr]

# Clean variables
friend_data_arr = nil
friend_positive_tags_arr = nil
friend_negative_tags_arr = nil

它在 generator#show Controller 中使用。当通过我的礼物生成引擎生成了一些礼物时,我将输入保存在 session 中(以防他们想在以后使用该信息)。我从不终止或终止这些 session ,以防这可能导致内存增加。

再次更新:我删除了这段代码,但内存仍然增加,所以我猜这部分不是它但类似的代码可能会导致错误?

最佳答案

这不太可能是我们的related_feed_categories 引起的。

您是否使用了很多文件?

您将 session 数据保留多长时间?看起来您有一个电子商务网站,您是否在 session 中保存对象?

基本上,我认为是文件,或 session ,或服务器崩溃时刷新的临时数据增加(memcache?)。

在半夜,我猜你的顾客少了。你能在高峰时段发布相同的内存图表吗?

可能与这个问题有关:Memory grows indefinitely in an empty Rails app

更新:

Rails 不会在客户端存储所有数据。我不记得默认存储,除非您选择 cookie::store,否则 rails 只会发送 session_id 之类的数据。

它们是关于 session 的一些指南,ActiveRecord::SessionStore 似乎是性能目的的最佳选择。而且您不应该在 session 中保留大型对象或 secret 数据。更多关于 session 的信息:http://guides.rubyonrails.org/security.html#what-are-sessions

在 2.9 部分,你有一个关于销毁 session 的解释,在一段时间内未使用。

我建议您存储提供搜索结果的 url,而不是将对象存储在 session 中。您甚至可以将其存储在数据库中,从而可以为您的客户节省少量研究,和/或默认加载上次使用的数据。

但在这个阶段,我们仍然不能完全确定 session 是罪魁祸首。为了确保这一点,您可以在测试服务器上尝试使用过期 session 对您的应用程序进行压力测试。所以基本上,你创建了大量的 session ,也许 20 分钟后 rails 不得不压制它们。如果您发现内存消耗有任何差异,它会缩小范围。

第一种情况: session 到期时内存显着下降,您知道这是与 session 相关的。

第二种情况:内存以更快的速度增加,但在 session 到期时不下降,你知道它与用户相关,但与 session 无关。

第三种情况:没有任何变化(通常内存增加),所以你知道它不依赖于用户数量。但我不知道是什么原因造成的。

当我说压力测试时,我指的是大量 session ,而不是真正的压力测试。您需要的 session 数取决于您的平均用户数。如果您有 50 个用户,那么在您的应用程序崩溃之前,20 -30 个 session 可能非常重要。因此,如果您手动拥有它们,请配置更高的过期时间限制。我们只是在寻找内存消耗的差异。

更新 2:

所以这很可能是内存泄漏。所以使用对象空间,它有一个 count_objects 方法,它将显示当前使用的所有对象。它应该缩小范围。当内存已经增加很多时使用它。

否则,你有 bleak_house,一个能够发现内存泄漏的 gem,仍然 ruby​​ 用于内存泄漏的工具不如 java 有效,但值得一试。

Github:https://github.com/evan/bleak_house

更新 3:

这可能是一种解释,这并不是真正的内存泄漏,但它会增加内存: http://www.tricksonrails.com/2010/06/avoid-memory-leaks-in-ruby-rails-code-and-protect-against-denial-of-service/

简而言之,符号会一直保存在内存中,直到您重新启动 ruby​​。因此,如果使用随机名称创建符号,内存将会增长,直到您的应用程序崩溃。字符串不会发生这种情况,它们是 GCed。

有点旧,但适用于 ruby​​ 1.9.x 试试这个:Symbol.all_symbols.size

更新 4:

所以,您的符号可能是内存泄漏。现在我们仍然需要找到它发生的地方。使用 Symbol.all_symbols。它为您提供列表。我想你可以将它存储在某个地方,并与新数组进行比较,以查看添加了什么。

它可能是 i18n,也可能是像 i18n 这样以隐式方式生成的其他东西。但无论如何,这可能会生成名称中带有随机数据的符号。然后这些符号就再也不用了。

关于ruby-on-rails - Rails 应用程序中的内存不断增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12578344/

相关文章:

ruby-on-rails - 无法将瘦服务器作为服务启动,RubyGems : Could not find thin

ruby-on-rails - 将渲染的 View 作为电子邮件发送

delphi - 优化 Delphi 中的类大小。有类似 "packed classes"的东西吗?

macos - Postgres.app 无法启动

java - 无法通过 Heroku 中的 Selenium webdriver(Java) 调用 headless chrome 驱动程序

ruby-on-rails - 当 rbenv 找不到时如何使用 Ruby 2.6.6?

swift - 为什么这个 Swift UIImage 函数会溢出我的内存?

java - Java中是否存在内存泄漏

mysql - Heroku Rails ClearDB Resque 连接

ruby-on-rails - Oauth2 提供者(Doorkeeper?)是用于登录的 Oauth2 使用者(Devise+OmniAuth)