【问题标题】:Ruby VM concurrency and parallelismRuby VM 并发性和并行性
【发布时间】:2011-11-09 11:52:58
【问题描述】:

我有一个关于 Ruby VM(Ruby 解释器)的一般性问题。它如何与多处理器一起工作?关于 Ruby 中的并行性和并发性,假设我有 4 个处理器。 VM 会通过内核自动将任务分配给处理器吗?通过缩放,假设我的 ruby​​ 进程占用了大量的 CPU 资源;如果我添加一个新的处理器会发生什么?操作系统是否负责将任务分配给处理器,或者每个 VM 是否会在一个处理器上工作?扩展我的 ruby​​ 应用程序的最佳方法是什么?我尽可能地尝试分离我的进程并使用 amqp 排队。还有其他想法吗?

如果您能将链接发送给我以获得更多解释,那就太好了。

提前致谢。

【问题讨论】:

    标签: ruby concurrency parallel-processing scalability multiprocessing


    【解决方案1】:

    Ruby 线程

    Ruby 语言本身通过线程模型支持并行执行;但是,实施决定是否使用额外的硬件资源。 “黄金标准”解释器(MRI Ruby)在 1.8 中使用“绿色线程”模型;线程是在解释器中完成的,并且只使用一个系统线程来执行。但是,其他人(例如 JRuby)利用 Java VM 创建实际的系统级线程以供执行。 MRI Ruby 1.9 添加了额外的线程功能,但 (afaik) 它仍然仅限于在线程停止 I/O 事件时切换线程上下文。

    高级线程

    通常情况下,操作系统会管理逻辑内核的线程分配,因为大多数应用软件实际上并不关心。在一些高性能计算案例中,软件会专门请求某些线程在特定逻辑核心上执行,以实现特定于架构的性能。用 Ruby 编写的任何东西都不太可能属于这一类。

    重构

    每个应用程序的性能限制通常可以通过首先重构代码来解决。利用更适合特定问题的语言或其他环境可能是最好的第一步,而不是立即跳到现有实现中的线程。

    示例

    我曾经在一个 Ruby on Rails 应用程序上工作过,当数据上传时,其中包含大量哈希映射函数步骤。最初的实现完全用 Ruby 编写,大约需要 80 秒才能完成。用 ANSI C 重写代码并利用更具体的内存分配,执行时间降至一秒以下(甚至不使用线程)。下一个瓶颈是将大量数据插入 MySQL,最终也从 Ruby 代码移到线程 C 代码中。我专门走这条路,因为 MRI Ruby 解释器很容易绑定到 C 代码。最终的结果是 Ruby 为 C 代码准备了环境,将其作为一个带参数的类上的 Ruby 实例方法调用,通过 C 代码的单线程进行哈希映射,最后以 OpenMP 工作队列模型的生成和在 MySQL 中执行插入操作。

    【讨论】:

    • 这是一个令人印象深刻的信息丰富的答案,因为它如此简短,并且在解决问题的关注点方面做得很好。 +1
    • 谢谢。我还应该注意,将单线程插入从 Ruby 移动到 C 并没有真正获得最初的性能。只有在我使用多线程实现之后,代码才看到更高的吞吐量。无论线程数和扩展插入的长度如何,它实际上都能以 45K 行/秒的速度饱和。
    • 我确信使用 C 来做耗时的过程是最好的,但就我目前的实现而言,10 K 行/秒已经绰绰有余,如果我收到更多请求,我会变得富有,我会聘请专家 :) 为我的解决方案我正在使用 async_query 和线程化连接,例如 (threads ||=[])
    相关资源