gpt4 book ai didi

ruby-on-rails - 如何在 Linux 上使用 Ruby 2.0 改进 unicorn 进程之间的内存共享

转载 作者:IT老高 更新时间:2023-10-28 12:37:50 25 4
gpt4 key购买 nike

Ruby 2.0 引入了一种写时复制友好的垃圾收集器。我的进程似乎没有保持共享内存超过几分钟 - 它似乎从shared_dirty 到 private_dirty 很快。

其他一些人已经成功地实现了这一点:

此程序可用于检查 Linux 上的内存统计信息:https://gist.github.com/kenn/5105061

我的 unicorn 配置:https://gist.github.com/inspire22/f82c77c0a465f1945305

由于某种原因,我的 unicorn 应用程序(也具有 preload_app=true)的共享内存要少得多。 Ruby 2.0-p195、rails 3.2、linux 2.6.18 (centos)

[root@thorn script]# ruby memstats.rb 4946
Process: 4946
Command Line: unicorn_rails worker[4] -c /u/apps/newap/current/lib/unicorn.rb -E production -D
Memory Summary:
private_clean 0 kB
private_dirty 56,324 kB
pss 60,256 kB
rss 83,628 kB
shared_clean 4,204 kB
shared_dirty 23,100 kB
size 108,156 kB
swap 68 kB

如果我完全关闭主进程(不仅仅是一个 HUP)然后重新启动它并在任何请求排队之前立即检查一个工作进程,我会得到一个更好的故事:

[root@thorn script]# ruby memstats.rb 5743
Process: 5743
Command Line: unicorn_rails worker[4] -c /u/apps/newap/current/lib/unicorn.rb -E production -D
Memory Summary:
private_clean 0 kB
private_dirty 21,572 kB
pss 27,735 kB
rss 66,296 kB
shared_clean 2,484 kB
shared_dirty 42,240 kB
size 91,768 kB
swap 0 kB

但在启动后 5 秒内,它们又回到了 ~20MB 的 shared_clean+shared_dirty。

我怀疑交换可能会导致问题,但在降低交换性并确保父进程和子进程都没有被换出(使用 swapstats.rb)之后,问题仍然存在。

我不明白什么是 shared_dirty 内存,以及它是如何变成私有(private)内存的。我也喜欢关于提高共享内存的生命周期和数量的建议。谢谢!

最佳答案

根据this answer ,你可能已经看到了,有一行写着:

Note that a "share-able" page is counted as a private mapping until it is actually shared. i.e. if there is only one process currently using libfoo, that library's text section will appear in the process's private mappings. It will be accounted in the shared mappings (and removed from the private ones) only if/when another process starts using that library.

我会做些什么来测试您是否获得了福利 outlined in this article , 将一个 10MB 的 xml 文件作为文字字符串直接放入您的源代码中。然后,如果您启动 20 名工作人员,您将能够查看您是否使用了 200MB 的内存,或者仅使用了 10MB,这与新的垃圾收集功能所预期的一样。

更新:

我正在查看 the unicorn source并找到了对 this wonderful article 的引用.

总而言之,它指出,为了使您的应用程序能够利用 Ruby 企业版的写时复制友好型垃圾收集器,您必须在 fork 之前将 GC.copy_on_write_friendly 设置为 true

if GC.respond_to?(:copy_on_write_friendly=)
GC.copy_on_write_friendly = true
end

根据您提供的 unicorn 配置文件​​,它似乎缺少分配。

另外,我喜欢阅读这些相关文章:

根据fork man page :

Under Linux, fork() is implemented using copy-on-write pages, so the only penalty that it incurs is the time and memory required to duplicate the parent's page tables, and to create a unique task structure for the child.

Since version 2.3.3, rather than invoking the kernel's fork() system call, the glibc fork() wrapper that is provided as part of the NPTL threading implementation invokes clone(2) with flags that provide the same effect as the traditional system call. (A call to fork() is equivalent to a call to clone(2) specifying flags as just SIGCHLD.) The glibc wrapper invokes any fork handlers that have been established using pthread_atfork(3).

根据 clone man page :

Unlike fork(2), these calls allow the child process to share parts of its execution context with the calling process, such as the memory space, the table of file descriptors, and the table of signal handlers.

所以,我读这个的意思是:linux 的 fork copy-on-write,这是 unicorn 实现内存共享所依赖的特性,直到 libc 2.2.3 才实现(请有人纠正我,如果我'这个解释是错误的)。

要检查您运行的是哪个版本的 libc,您可以键入:

ldd --version

或者,找到 glibc 并直接运行它。在我的系统上,它在以下位置找到了该文件:

locate libc.so
/lib/x86_64-linux-gnu/libc.so.6

关于ruby-on-rails - 如何在 Linux 上使用 Ruby 2.0 改进 unicorn 进程之间的内存共享,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17180814/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com