【问题标题】:Why does repeated JSON parsing consume more and more memory?为什么重复的 JSON 解析会消耗越来越多的内存?
【发布时间】:2013-06-17 17:18:59
【问题描述】:

似乎在 Ruby 中一遍又一遍地解析同一个 JSON 文件会占用越来越多的内存。 考虑下面的代码和输出:

  1. 为什么第一次迭代后内存没有释放?
  2. 为什么一个 116MB 的 JSON 文件解析后会占用 1.5Gb 的 RAM?考虑到文本文件被转换为哈希值,这令人惊讶。我在这里错过了什么?

代码:

require 'json'

def memused
  `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)[1]/1024
end

text = IO.read('../data-grouped/2012-posts.json')
puts "before parsing: #{memused}MB"
iter = 1
while true
  items = JSON.parse(text)
  GC.start
  puts "#{iter}: #{memused}MB"
  iter += 1
end

输出:

before parsing: 116MB
1: 1840MB
2: 2995MB
3: 2341MB
4: 3017MB
5: 2539MB
6: 3019MB

【问题讨论】:

  • 垃圾收集器随心所欲地运行,这与希望它什么时候......
  • 程序内存不足时不应该运行GC吗?当 json 为 400mb 时,它在第一个迭代中使用 5gigs 的 ram,然后开始使用交换(这使得解析需要几十分钟而不是几秒钟)。我将如何调用 GC 来清理内存?
  • 正在使用哪些版本的 Ruby 和 JSON?
  • 您的意思是“MB”而不是“Mb”吗?在我的世界中,“MB”表示兆字节,“Mb”表示兆比特,两者略有不同。
  • 是的,我的意思是兆字节。改为MB。我正在使用红宝石 2.0.0-p0。不知道如何找出 json 版本。看来我没有安装 json gem,但代码仍然有效。gem check json 没有返回任何内容

标签: ruby json memory memory-leaks


【解决方案1】:

当 Ruby 解析 JSON 文件时,它会创建许多中间对象来实现目标。这些对象会一直保留在内存中,直到 GC 开始工作。

如果JSON文件结构复杂,数组和内部对象多,数量也会增长很快。

您是否尝试调用“GC.start”来建议 Ruby 清理未使用的内存?如果内存量 显着减少,这表明只是用于解析数据的中间对象,否则,您的数据结构很复杂,或者您的数据中有一些东西是lib无法释放的。

对于大型 JSON 处理,我使用 yajl-ruby (https://github.com/brianmario/yajl-ruby)。它是 C 实现的,占用空间小。

【讨论】:

  • 谢谢,我会这样做的。但这并不能回答我的问题。
  • @user1027996 我编辑了帖子并包含了一些信息。
  • 添加 GC.start 并没有什么不同
  • @user1027996:JSON 可能会创建符号等,最终可能导致内存泄漏,因为它们从未被释放。
  • 据我所知GC.start 不会强制进行垃圾收集,但只有您向解释器提出建议,如果它在那里运行,您会很高兴。并为yajl +1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多