我的应用程序在Puma(2.4)集群模式下运行,有4个工人。最初,它们总共使用不到2GB的RAM,但不断增长,运行20小时后最终使用了7GB。
通过使用ObjectSpace,我发现字符串对象的数量增长非常快,从大约30万个增加到每个工作者中的4-5百万个。
然后,我使用以下脚本将这些字符串按前60个字符分组并进行计数:
counts = Hash.new(0)
ObjectSpace.each_object do |o|
next unless (o.class == String)
counts[o[0,60]] += 1
end
counts = counts.to_a.sort_by(&:last);
puts counts[-10..-1]
事实证明,这些字符串中的大多数都是来自活动记录的SQL日志记录
ObjectSpace.count_objects
# result
{
:TOTAL => 2439593,
:FREE => 209200,
:T_OBJECT => 65944,
:T_CLASS => 11343,
:T_MODULE => 2003,
:T_FLOAT => 13,
:T_STRING => 1821445,
:T_REGEXP => 6570,
:T_ARRAY => 157012,
:T_HASH => 27477,
:T_STRUCT => 1406,
:T_BIGNUM => 1393,
:T_FILE => 142,
:T_DATA => 75081,
:T_MATCH => 1334,
:T_COMPLEX => 1,
:T_RATIONAL => 2809,
:T_NODE => 51890,
:T_ICLASS => 4530
}
# top 10 string
["PricingRule Exists: SELECT" , 74632]
[": SELECT COUNT(*) FROM `re" , 85454]
["CACHE: SELECT `companies`" , 93045]
["PricingRule Load: SELECT " , 114169]
["Page Load: SELECT `pages`" , 140245]
[": SELECT COUNT(*) FROM `pa" , 182274]
["Customer Load: SELECT `cu" , 191972]
["Company Load: SELECT `com" , 253025]
["Page Load: SELECT `pages`." , 320267]
["DestinationCountry Load: S" , 413299]
我使用Rails 4、Ruby 2、mysql2(v0.3.13),并将日志级别设置为warn,但这些SQL字符串仍然存储在内存中,并不断增加。
有人对这个问题有任何想法或经验吗?如果你能帮忙,我将不胜感激。
谢谢!
这些字符串可以来自"sql.active_record"事件,原因可能是您订阅了"sql.active_record"事件,并将这些字符串保留在对象中,以便GB无法释放它们。
ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
end
请确保在使用后取消订阅。