Ruby MRI在Thread.new时复制内存分配
似乎MRI为每个新线程重复内存分配 我使用UbuntuX64、ruby-2.2.4(rvm),我得到的是: 刚开始的irb: 我看到Ruby MRI在Thread.new时复制内存分配,ruby,multithreading,mri,Ruby,Multithreading,Mri,似乎MRI为每个新线程重复内存分配 我使用UbuntuX64、ruby-2.2.4(rvm),我得到的是: 刚开始的irb: 我看到pmap-d165659760K(已分配内存,或程序堆栈[man-pmap(1)]的“[stack]”内存使用情况: 创建线程时: 我看到pmap-d 1656127352K内存使用情况: 所以,我看到了内存分配的重复59760K->127352K 这种行为类似于fork()调用的结果,该调用用于创建新流程,为新流程创建其调用流程数据的副本(“此上下文中没
pmap-d1656
59760K(已分配内存,或程序堆栈[man-pmap(1)]的“[stack]”内存使用情况:
创建线程时:
我看到pmap-d 1656
127352K内存使用情况:
所以,我看到了内存分配的重复59760K->127352K
这种行为类似于
fork()
调用的结果,该调用用于创建新流程,为新流程创建其调用流程数据的副本(“此上下文中没有“写时拷贝”)
但线程是在同一进程中创建的,并共享其数据,它看起来很奇怪
实际上,这意味着Ruby中的线程在内存使用方面具有类似于进程的限制:当分配的内存接近物理内存大小时,新线程的创建将失败
我很好奇,为什么
更新
这不是复制内存,而是为每个线程分配~50K的额外内存。
感谢@tadman的建议,这是一种开销,而不是以fork()的方式复制内存。每个线程都必须为堆栈分配足够的内存,堆栈大小由定义,但即使如此,这也不能解释此处看到的所有内存使用情况。我已经在Fedora机器上复制到一定程度,但我可以毫无问题地运行约500个线程。@tadman,是的,我知道线程数的限制可能看起来并不重要,但我的问题来自一个真实的案例,我在不太小的Rails项目中使用了线程,我得到了内存的限制。但问题是,如果线程已经有了内存空间,为什么它必须分配更多内存?它使用共享对象,从这点上看,它只是一个并发执行的例程。即使它创建了变量——就像其他块中的其他变量一样,不是吗?我不是100%确定MRI的内部结构,但我知道它在全局解释器锁和各种历史兼容性方面有很多问题。新线程确实需要它自己的一些东西的副本,但是随着改进的进行,它需要的东西在版本1.9到2.4之间有很大的不同。堆是共享的,但其他元素不是,特别是堆栈。看来你的建议很重要。我尝试过用
arr=10000000.times.injection([]){a,I | aIf分配一些内存,如果你能想出更多关于分配内容的具体指标,如果这确实是错误的,我相信Ruby性能团队可能会感兴趣。我不确定MRI中的线程C代码有多粗糙,但这是一个开始挖掘的地方。