Rails app中的内存不断增加

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

来自New Relic的屏幕转储,Dyno内存使用情况

更新:当从New Relic进行此屏幕转储时。我已经安排了每小时重启web dyno(两个web dynos中的一个)。因此,它没有达到500Mb的崩溃水平,它实际上得到了一点sig锯模式。尽管如此,问题根本没有得到解决,只有一些症状。你可以看到早上不是那么忙,但下午更忙。

更新 :当从New Relic获取此屏幕转储(下面的那个)时。 我已经安排了每小时重启web dyno(两个web dynos中的一个)。 因此,它没有达到500Mb的崩溃水平,它实际上得到了一点sig锯模式。 尽管如此,问题根本没有得到解决,只有一些症状。 你可以看到早上不是那么忙,但下午更忙。 我在11.30上传了一个小细节,即使它在统计数据中显示也不会影响问题。

还可以注意到,即使图形显示AVG存储器,也是MIN存储器继续增加。 即使图形似乎在图形中暂时下降,最小内存保持不变或增加。 MIN记忆永不减少!

该应用程序将(没有dyno重新启动)内存增加,直到它达到Heroku的最高级别,并且应用程序崩溃执行过期类型的错误。

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

执行故障排除

答:我认为问题在于application_controller中的before_filter( 应用程序控制器中的变量会导致Rails中的内存泄漏吗? )但这不是问题。

B.我安装了oink但它没有给出任何结果(根本)。 它创建了一个oink.log,但是当我运行“heroku run oink -m log / oink.log”时,无论什么门槛都没有给出任何结果。

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

D.我用谷歌搜索并阅读了主题中的大多数文章,但我不是更聪明。

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

我的问题:

Q1。 我真正想知道的是每个请求增加的变量的名称,或者至少哪个控制器使用最多的内存。

Q2。 一个控制器如下面的代码会增加内存吗?

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

(对不起,因为某种原因,所以不会重新格式化代码以便于阅读)。

我之后是否需要使用“related_feed_categories = nil”“kill”“related_feed_categories”或垃圾收集器是否处理该问题?

Q3。 我要找的主要内容是什么? 现在我无法缩小它的全部范围。 我不知道要深入研究哪部分代码,我真的不知道该寻找什么。

Q4。 万一我真的无法解决问题。 是否有任何在线咨询服务,我可以发送我的代码,让他们找到问题?

谢谢!

更新 。 收到评论后,它可能与会话有关。 这是我认为可能不好的代码的一部分:

 # 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 

它用在生成器#show控制器中。 当通过我的礼物生成引擎生成一些礼物时,我将输入保存在会话中(如果他们想在稍后阶段使用该信息)。 我永远不会杀死或过期这些会话,以防万一这会导致内存增加。

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

我们的related_feed_categories不太可能引发这种情况。

你使用了很多文件吗?

你保持会话数据多长时间? 看起来你有一个电子商务网站,你在会话中保留对象吗?

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

在半夜,我想你的客户较少。 你可以在高峰时段张贴相同的记忆图表吗?

它可能与此问题有关: 内存在空Rails应用程序中无限增长

更新:

Rails不会在客户端存储所有数据。 我不记得默认存储,除非你选择cookie :: store,rails只发送像session_id这样的数据。

它们几乎没有关于会话的指导,ActiveRecord :: SessionStore似乎是性能目的的最佳选择。 而且你不应该在会话中保留大型对象或秘密数据。 更多关于会议的内容: http : //guides.rubyonrails.org/security.html#what-are-sessions

在2.9部分中,您有一个解释来销毁会话,在一段时间内未使用。

我建议你存储提供搜索结果的url,而不是在会话中存储对象。 您甚至可以将其存储在数据库中,从而可以为您的客户节省一些研究,并且/或者默认加载最后使用的数据。

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

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

第二种情况:内存以更快的速度增加,但在会话到期时不会丢失,您知道它与用户有关,但与会话无关。

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

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

更新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-针对-拒绝服务/

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

有点旧,但对ruby 1.9.x有效试试这个:Symbol.all_symbols.size

更新4:

所以,你的符号可能是内存泄漏。 现在我们仍然需要找到它发生的位置。 使用Symbol.all_symbols。 它给你列表。 我想你可以将它存储在某处,并使用新数组进行差异,以便查看添加的内容。

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

假设category_from_feed返回一个字符串(或者可能是一个符号),则增加300MB的幅度是不太可能的。 您可以通过对此进行分析来粗略地达到此目的:

 4_000_000.times {related_feed_categories << "Loooooooooooooong string" } 

这个片段会使内存使用量大约增加110MB。

我会查看读取文件的数据库连接或方法,然后不要关闭它。 我可以看到它与feed有关,这可能意味着你可能正在使用XML。 这也是一个起点。


将此作为答案发布,因为这在评论中看起来很糟糕:/