在多进程 fork 服务器中,'require' 比 'autoload' 和 Ruby 2 更可取吗?
Is 'require' preferrable to 'autoload' with Ruby 2 in a multi-process fork server?
我正在阅读 this 文章。我关心的是 autoload
对比 require
的好处。通过阅读这篇文章,我了解到对多线程服务器使用 autoload
是不好的,因为一个线程可能会尝试加载一个不在内存中的对象。
文章说多进程服务器呢?自动加载对那些有好处吗?然后它说这取决于。如果服务器使用 fork(它为每个请求生成一个新进程),例如 Phusion Passenged,而您使用的是 Ruby 2,那么自动加载就没有好处。
原因是因为Ruby 2 使用了写时复制语义。这意味着使用 require
比 autoload
更好。使用写时复制语义,如果我们在启动时加载 Foo::Bar
,我们将在所有进程之间共享一份 Foo::Bar
。因此,不会有很大的内存占用。
但是,如果我们不使用 Ruby 2 并且我们不使用使用 fork 的多进程服务器,则每个进程最终将加载自己的 Foo::Bar
副本,这可能会导致更高的内存使用率。因此,在那种情况下 autoload
优于 require
.
我对文章的解读是否正确?
我想你已经明白了,但为了清楚起见,最好重申几点:
重要的区别不完全在 require
和 autoload
之间,而是在预加载和延迟加载之间。预加载在分叉时是线程安全和内存高效的,但它会减慢服务器启动速度。延迟加载在分叉时既不是线程安全的也不是内存有效的,但它允许快速服务器启动。 require
或 autoload
以及 Rails eager_autoload
预加载; autoload
本身延迟加载。
考虑到上述情况,不同的服务器和 Ruby 版本会针对延迟加载和急切加载提出不同的问题:
- 在线程服务器中,延迟加载是不安全的,因此需要(咳咳)预加载。
- 在事件服务器中,延迟加载是可以的,所以你也可以延迟加载来快速启动服务器。
- 在分叉服务器中,延迟加载是安全的,但内存效率低下。
- 在 Ruby < 2 中,预先加载也是内存效率低下的,因为 Ruby < 2 不支持写时复制。所以你不妨延迟加载。 (实际上,你应该做的是升级到当前 Ruby。)
- 在 Ruby >= 2 中,预先加载是内存高效的,因为它利用了写时复制的优势,因此是首选。
我正在阅读 this 文章。我关心的是 autoload
对比 require
的好处。通过阅读这篇文章,我了解到对多线程服务器使用 autoload
是不好的,因为一个线程可能会尝试加载一个不在内存中的对象。
文章说多进程服务器呢?自动加载对那些有好处吗?然后它说这取决于。如果服务器使用 fork(它为每个请求生成一个新进程),例如 Phusion Passenged,而您使用的是 Ruby 2,那么自动加载就没有好处。
原因是因为Ruby 2 使用了写时复制语义。这意味着使用 require
比 autoload
更好。使用写时复制语义,如果我们在启动时加载 Foo::Bar
,我们将在所有进程之间共享一份 Foo::Bar
。因此,不会有很大的内存占用。
但是,如果我们不使用 Ruby 2 并且我们不使用使用 fork 的多进程服务器,则每个进程最终将加载自己的 Foo::Bar
副本,这可能会导致更高的内存使用率。因此,在那种情况下 autoload
优于 require
.
我对文章的解读是否正确?
我想你已经明白了,但为了清楚起见,最好重申几点:
重要的区别不完全在
require
和autoload
之间,而是在预加载和延迟加载之间。预加载在分叉时是线程安全和内存高效的,但它会减慢服务器启动速度。延迟加载在分叉时既不是线程安全的也不是内存有效的,但它允许快速服务器启动。require
或autoload
以及 Railseager_autoload
预加载;autoload
本身延迟加载。考虑到上述情况,不同的服务器和 Ruby 版本会针对延迟加载和急切加载提出不同的问题:
- 在线程服务器中,延迟加载是不安全的,因此需要(咳咳)预加载。
- 在事件服务器中,延迟加载是可以的,所以你也可以延迟加载来快速启动服务器。
- 在分叉服务器中,延迟加载是安全的,但内存效率低下。
- 在 Ruby < 2 中,预先加载也是内存效率低下的,因为 Ruby < 2 不支持写时复制。所以你不妨延迟加载。 (实际上,你应该做的是升级到当前 Ruby。)
- 在 Ruby >= 2 中,预先加载是内存高效的,因为它利用了写时复制的优势,因此是首选。