Ruby forking和CoW运行GC正在扼杀性能

时间:2015-04-27 15:54:36

标签: ruby linux garbage-collection fork copy-on-write

问题是:在2.2.1中分叉和调用GC时,内存重复。这个问题的主要问题是,当操作大量数据(范围为3GB)时,我的机器只能在一个分叉后被杀死。

我们编写了一个小程序来重现该问题(参见附件)。

程序实例化一个对象,然后分成两个进程。 在子进程中调用GC。 内存分配(由/ proc / pid / smaps给出)从共享变为私有,从而表明内存消耗加倍。

这是程序的输出(大小以mb为单位):

https://bugs.ruby-lang.org/issues/10559#change-50245

我们已经使用ruby 1.9.3,2.1.3和2.2.1(最新版)在Ubuntu 14.04上测试了该程序。测试已经在新安装的Ubuntu机器上进行,因此没有其他软件参与其中。

我们还试图分叉10个孩子并看到内存消耗增加了10倍,这个问题只发生在运行GC之后。

问题:这个问题的根源是什么(Ruby,内核,Ubuntu)以及可以用它做什么?

程序的源代码可以在这里找到:https://bugs.ruby-lang.org/issues/10559#change-50245

编辑:

这是我工作的代码。

def memory_object( size)
    count = size/20
    count.times do
       result << "%20.18f" % rand
    end

    return result
end

big_memory = memory_object( 1000 * 1000* 30)

pid = fork do
    big_memory_1 = memory_object( 1000 * 1000*30)
    sleep( 1)
    STDOUT.flush
    exit!
end

Process.wait( pid)

如果运行上面的代码并使用linux上的smaps监视共享内存,你会发现在子进程中创建新对象的那一刻,整个内存变得私密但不应该因为我我甚至没有修改原始对象。然而,有趣的是,如果附加到数组的字符串是如下所示创建的,那么一切都表现正常。

result << rand.to_s

我怀疑这是因为底部版本产生的垃圾更少。但即使我在前几次强制GC之前,它仍然会发生。我怀疑这是因为一切都在GC堆上分配,实际上已经修改了,这导致了写时复制。有可能吗?

0 个答案:

没有答案