Ruby Ruby 2.2 中实验性的采用 Vfork

kewin · 2015年01月08日 · 最后由 abbshr 回复于 2015年03月20日 · 6179 次阅读
本帖已被管理员设置为精华贴

Ruby 2.2 release notes 中提到,除了 Symbol GC 和 Incremental GC 外,还实验性的引入 vfork 这两天看到几篇文章

fork 和 vfork 的差别: fork 是 创建一个子进程,并把父进程的内存数据 copy 到子进程中。 vfork 是 创建一个子进程,并和父进程的内存数据 share 一起用。 这两个的差别是,一个是 copy,一个是 share。(关于 fork,可以参看酷壳之前的《一道 fork 的面试题》)

你 man vfork 一下,你可以看到,vfork 是这样的工作的,

1)保证子进程先执行。 2)当子进程调用 exit() 或 exec() 后,父进程往下执行。

但是目前 vfork 还是存在一些风险

vfork 的 man page 里面不是说了最好不要用 vfork 么?虽然没有明确这么说,但是感觉就是不希望用户用。

来,试试把 Unicorn 的 fork 改成 vfork 看看能否节省内存、共享全局变量

试了一下,将 Unicorn 的 fork {} 改成 vfork,能跑起来 Rails,Ruby China 的代码上面展示看起来没问题。 我又尝试写了个全局变量,没发现进程之间能共享呢,多次刷新那个全局变量的 object_id 在变 哦,是 Master 和 Child 共享,我搞错了


ps aux 看了一下,两种方式的内存占用量也没区别

#5 楼 @huacnlee fork 是用写时复制 ( copy on write ) 技术来实现的, 也就是说如果父进程的代码段没有在子进程修改的话, 子进程也同样使用这个代码段. 所以内存并不会额外消耗.

#6 楼 @lyfi2003 @huacnlee 确切的说直到父进程和子进程其中之一,需要对共享内存的数据修改时才会进行内存复制。这也是 cow 的优点,将内存复制推迟。

However vfork(2) is still not well understood and a potentially harmful system call. We would like to experiment to find out how much benefit can be gained by gathering performance data and use cases.

linux 下就不要用 vfork 啦, fork 用了 cow 之后就已经和 vfork 差不多,还直接很多。但是在 bsd like 系统里面可能就需要用 vfork 了

目前 unicorn 的 fork 是复制运行时本身的 内存,ruby 代码用的内存可靠 copy on write 共享,而这个 vfork 应该是系统的 api,即是运行时本身的代码 (也就是 ruby 的 c 语言编写的源码) 使用的堆栈 (具体哪些还得去看看 man) 也共享

没啥意义啊,fork 引入了写时复制,代价不会比 vfork 高

《LSP》:

vfork 是个历史遗留, linux 系统本不应该实现它

即使提供了写时复制机制, vfork 也比 fork 快, 因为他没有进行页表项的复制.

严格来讲, vfork 的所有实现都是有 bug 的: 如果 exec 调用失败了, 父进程将一直挂起, 直到子进程采取措施或退出.程序应该更倾向于使用 fork.

需要 登录 后方可回复, 如果你还没有账号请 注册新账号