7

我正在考虑将我们的 ruby​​ 解释器更新为 JRuby,这非常令人头疼,因为我们不得不从我们的应用程序中删除任何 2.x 特定语法并求助于 ruby​​ 1.9.3 兼容性。这不是世界末日。

到了运行应用程序的时候,我发现我们不能在集群模式下使用 Puma。问题是,鉴于过去几年对 MRI 的所有修复和更改,拥有“真实线程”的好处仍然有效吗?

更新

为了使这更客观,问题是,“最新版本的 MRI 是否不需要采用 JRuby 来实现与本地线程相同的好处?”

4

3 回答 3

9

最新版本的 MRI 是否不需要采用 JRuby 来实现与本机线程相同的好处?

答案是不。它并没有否定需求,它取决于您在其他答案中提到的应用程序。

此外,JRuby 不允许您在集群模式下运行,但就您的问题而言,这并不是真正的问题,因为它是多线程和并行的。只需在单模式下运行所需的线程数即可。它应该非常好,如果不是更轻量级的话。


让我为您提供一些参考资料,这些参考资料可以提供更多见解并让您进一步挖掘。

这个答案讨论了 MRI 和 JRuby 使用 Puma(最多 40 个线程)测试并发请求的实验。它相当全面。

这些实验可在 GitHub、MRIJRuby上获得。

需要注意的是它只测试并发请求,但在控制器中没有竞争条件。但是,我认为您可以从本文删除 config.threadsafe 中实现测试!没有太多的努力。

JRuby 和 MRI 的区别在于 JRuby 可以并行执行代码。MRI 受 GIL 限制,一次只能执行一个线程。您可以在这篇文章中阅读有关 GIL 的更多信息,没人了解 GIL

结果相当令人惊讶。MRI 比 JRuby 快。随意改进和添加比赛条件。

请注意,两者都是多线程的并且不是线程安全的。真正的区别在于 MRI 不能并行执行代码,而 JRuby 可以。


如果实验表明 MRI 速度更快,您可能会想说为什么我会回答“否”。

我认为我们需要更多的实验,尤其是现实世界的应用。

如果您认为 JRuby 应该更快,因为它可以并行执行代码,那么原因可能是:

  • 实验应该在高度并行的环境中执行,以便能够利用 JRuby 的潜力。
  • 它可能是 Web 服务器本身。也许 Puma 没有充分利用 JRuby 的潜力。MRI 有一个 GIL,为什么它在处理请求方面比 JRuby 快?
  • 其他更深入的因素可能是相关的,我们还没有发现......
于 2015-05-14T03:17:51.017 回答
4

确实取决于您使用 Web 服务器的情况(您应该对此有最好的理解)......如果您觉得您的产品在 MRI 下运行良好,而不是您可能没有那么多的并发性。与 Rubinius/JRuby 相比, puma 的README几乎解释了您在 MRI 下得到的结果:

在 MRI 上,有一个全局解释器锁 (GIL),可确保一次只能运行一个线程。但是,如果您正在执行大量阻塞 IO(例如对 Twitter 等外部 API 的 HTTP 调用),Puma 仍然通过允许阻塞 IO 并发运行来提高 MRI 的吞吐量(基于 EventMachine 的服务器,例如 Thin 关闭此功能,需要您可以使用特殊库)。你的旅费可能会改变。为了获得最佳吞吐量,强烈建议您使用带有真实线程的 Ruby 实现,例如 Rubinius 或 JRuby

... 所以一句话:**你可以在MRI下有多个线程,但你没有并行性**

于 2014-09-29T13:13:16.840 回答
3

恕我直言,这取决于您的应用程序做什么。

我已经在我的 Rails 应用程序上测试了 MRI/YARV 和 JRuby。由于该应用程序所做的大部分工作是路由 HTTP 请求、从数据库中获取数据、应用简单的业务逻辑并写入数据库,因此并行性并不是什么大问题。MRI 上的 Puma 确实处理用于阻塞 IO 操作(DB、API)的多线程。超出此范围的任务(图像处理、处理报告数据、调用外部 API 等)可能无论如何都应该由后台作业处理(我推荐https://github.com/brandonhilkert/sucker_punch)。

根据您的部署需要,内存消耗可能是一个更大的问题,而且 JRuby 非常需要内存。就我而言,几乎是 2 倍的内存。

如果您在 Heroku 上部署应用程序,您可能会发现能够在 1 个测功机上同时运行 2 个实例,从而获得更多收益。

于 2014-12-17T19:31:14.807 回答