【发布时间】:2020-09-17 18:59:30
【问题描述】:
我有一个导出工作,从我们的 MySQL 数据库中导出大量数据。随着数据的增长,我注意到 sidekiq 的工作占用了太多的内存。服务器有 32GB,导出完成后需要 28GB。当我停止 sidekiq 进程时,内存使用量降至 8GB。
我已经按照这里的指南https://github.com/mperham/sidekiq/wiki/Problems-and-Troubleshooting
- 使用
MALLOC_ARENA_MAX=2防止内存碎片 - 清除查询缓存
ActiveRecord::Base.connection.clear_query_cache
我正在使用 Ruby 2.6.5p114,并尝试通过在生产中创建新的 rails 应用程序并将我的数据库用作后端来隔离问题:
gem install rails --version 5.2.4.3
rails new debug -d mysql
我创建了一个空模型以避免代码中可能导致问题的自定义方法:
class Variant < ApplicationRecord
end
此脚本只是从数据库中加载 1 个 Mio 对象并打印内存使用情况:
# memory.rb
def memory
(`ps -o rss= -p #{Process.pid}`.to_i.to_f / 1024).to_s + " MB"
end
def load_variants
puts "load_variants..."
Variant.uncached do
variants = Variant.limit(1_000_000).to_a
puts "variant.count: #{variants.count}"
end
end
puts memory
load_variants
puts memory
puts "GC.start..."
GC.start
puts memory
# second run
load_variants
puts memory
puts "GC.start..."
GC.start
puts memory
这是输出:
root@6e79d7a97d9c:/usr/src/debug# rails r memory.rb
76.93359375 MB
load_variants...
variant.count: 1000000
2436.3125 MB
GC.start...
2421.046875 MB
load_variants...
variant.count: 1000000
2436.3828125 MB
GC.start...
2436.3984375 MB
- 以
76.93359375 MB开头 - 加载1个Mio对象后,内存增加到
2436.3125 MB - 垃圾回收将内存减少到
2421.046875 MB,但我预计会有明显更高的下降! - 有趣的是,第二次运行,只会增加内存到
2436.3828125 MB - 最后一个
GC.start不知何故增加内存一点点到2436.3984375 MB
所以我想知道这是怎么回事? ActiveRecord 中一定有一些我不知道的东西,我想了解这一切是如何工作的,以及为什么没有释放内存。
按照这个逻辑,每个读取数据的请求都会增加内存,但我认为在请求-响应周期内使用时会有所不同。
【问题讨论】:
-
github.com/rails/rails/blob/master/guides/bug_report_templates/… AR 错误模板非常适合创建用于测试的自包含代码。
-
@23tux 你有解决这个问题的办法吗?
标签: ruby-on-rails ruby memory memory-leaks rails-activerecord