57

Ruby 在某些事情上很慢。但它的哪些部分是最有问题的?

垃圾收集器对性能有多大影响?我知道我曾经有过单独运行垃圾收集器需要几秒钟的时间,尤其是在使用 OpenGL 库时。

我在 Ruby 中使用过特别慢的矩阵数学库。ruby 如何实现基本数学有问题吗?

Ruby 中是否有任何无法有效实现的动态特性?如果是这样,其他语言如 Lua 和 Python 是如何解决这些问题的?

最近有没有显着提高性能的工作?

4

9 回答 9

70

红宝石很慢。但它的哪些部分是最有问题的?

它对方法进行“后期查找”,以提供灵活性。这会减慢它的速度。它还必须记住每个上下文的变量名以允许 eval,因此它的帧和方法调用更慢。目前它还缺乏一个好的 JIT 编译器,虽然 MRI 1.9 有一个字节码编译器(更好),并且 jruby 将它编译成 java 字节码,然后(可以)通过 HotSpot JVM 的 JIT 编译器编译,但它最终是关于速度与1.9相同。

垃圾收集器对性能有多大影响?我知道我曾经有过单独运行垃圾收集器需要几秒钟的时间,尤其是在使用 OpenGL 库时。

http://www.igvita.com/2009/06/13/profiling-ruby-with-googles-perftools/上的一些图表我会说它需要大约 10%,这相当多——你可以通过增加 gc.c 中的 malloc_limit 并重新编译来减少这种影响。

我在 Ruby 中使用过特别慢的矩阵数学库。ruby 如何实现基本数学有问题吗?

Ruby 1.8“没有”实现基本数学,它实现了数字类,你每次调用都会调用一次像 Fixnum#+ Fixnum#/ 这样的东西——这很慢。Ruby 1.9 通过内联一些基本的数学运算有点作弊。

Ruby 中是否有任何无法有效实现的动态特性?如果是这样,其他语言如 Lua 和 Python 是如何解决这些问题的?

我敢肯定,诸如评估之类的事情很难有效地实施。Ruby的踢球者是,它必须在另一个线程中适应一个自发改变班级定义的人,因此必须非常保守。

最近有没有显着提高性能的工作?

1.9就像2倍加速。它也更加有效。Jruby一直在努力提高速度[并且在GC中花费的时间比KRI花费的时间少]。除此之外,除了我一直从事的小爱好事情之外,我还不知道很多。还请注意,由于编码友好性,1.9的字符串有时会变慢。

于 2009-06-22T17:46:10.470 回答
11

Ruby 非常适合快速交付解决方案。提供快速解决方案的情况较少。这取决于您要解决什么样的问题。我想起了 90 年代初在旧 CompuServe MSBASIC 论坛上的讨论:当被问及 Windows 开发、VB 还是 C 哪个更快时,通常的回答是“VB,大约 6 个月”。

在其 MRI 1.8 形式中,Ruby 在执行某些类型的计算密集型任务时相对较慢。与大多数主流编译语言相比,几乎所有解释语言都会受到这种影响。

原因有很多:一些相当容易处理(例如 1.8 中的原始垃圾收集),一些则不太容易。

1.9 解决了一些问题,尽管它可能需要一段时间才能普遍可用。其他一些以预先存在的运行时为目标的实现,例如 JRuby、IronRuby、MagLev,有可能显着加快速度。

关于数学性能,看到相当慢的吞吐量我不会感到惊讶:这是您为任意精度付出的代价的一部分。再次,选择你的问题。我已经在 Ruby 中解决了 70 多个Project Euler问题,几乎没有一个解决方案需要花费超过一分钟的时间来运行。你需要它多快运行,多快需要它?

于 2009-06-18T08:54:06.770 回答
9

最成问题的部分是“每个人”。

如果那个“每个人”从来没有真正使用过这种语言,那就加分吧。

说真的,1.9 快得多,现在与 python 不相上下,而 jruby 比 jython 快。

垃圾收集器无处不在;例如,Java 有一个,它在动态内存处理方面比 C++ 更快。Ruby 不太适合数字运算。但是很少有语言是这样的,所以如果你的程序中有任何语言的计算密集型部分,你最好用 C 重写它们(Java 由于其原始类型而在数学上很快,但它为它们付出了高昂的代价,它们显然是 # 1 在语言中最丑陋的部分)。

至于动态特性:它们并不快,但是在静态语言中没有它们的代码可能会更慢;例如,java 将使用 XML 配置,而不是使用 DSL 的 Ruby;而且它可能会更慢,因为 XML 解析成本很高。

于 2009-06-18T08:31:20.387 回答
8

嗯 - 几年前我在一个项目中工作,我用 Ruby 性能刮了桶,我不确定从那以后有多大变化。现在它是警告购买者 - 你必须知道不要做某些事情,坦率地说游戏/实时应用程序将是其中之一(因为你提到了 OpenGL)。

扼杀交互性能的罪魁祸首是垃圾收集器——这里的其他人提到 Java 和其他环境也有垃圾收集,但 Ruby 必须阻止世界运行。也就是说,它必须停止运行你的程序,从头开始扫描每个寄存器和内存指针,标记仍在使用的内存,然后释放其余的。发生这种情况时,该过程不能中断,您可能已经注意到,它可能需要数百毫秒。

它的执行频率和长度与您创建和销毁的对象数量成正比,但除非您完全禁用它,否则您无法控制。我的经验是有几个不令人满意的策略来平滑我的 Ruby 动画循环:

  • GC.disable / GC.enable 围绕关键动画循环,也许是一个机会主义的 GC.start 在它不会造成任何伤害时强制它去。(因为我当时的目标平台是一台 64MB 的 Windows NT 机器,这会导致系统偶尔耗尽内存。但从根本上说这是一个坏主意 - 除非您可以在执行此操作之前预先计算您可能需要多少内存,否则您'冒着内存耗尽的风险)
  • 减少您创建的对象数量,从而减少 GC 要做的工作(减少其执行的频率/长度)
  • 用 C 重写你的动画循环(一个逃避,但我选择了那个!)

这些天我可能还会看看 JRuby 是否可以作为替代运行时工作,因为我相信它依赖于 Java 更复杂的垃圾收集器。

我发现的另一个主要性能问题是不久前尝试用 Ruby 编写 TFTP 服务器时的基本 I/O(是的,我为我的性能关键项目选择了所有最好的语言,这只是一个实验)。最简单的最紧凑的循环简单地响应一个 UDP 数据包与另一个,包含文件的下一部分,肯定比股票 C 版本慢 20 倍。我怀疑基于使用低级 IO(sysread 等)可能已经进行了一些改进,但速度缓慢可能只是因为没有低级字节数据类型 - 每个小读取都被复制到一个细绳。虽然这只是猜测,我并没有进一步推进这个项目,但它警告我不要依赖 snappy I/O。

尽管我在这里没有完全更新,但最近的主要速度增加是虚拟机实现在 1.9 中重做,从而加快了代码执行速度。但是我认为 GC 没有改变,而且我很确定 I/O 方面没有什么新东西。但我并不完全了解最新的 Ruby,所以其他人可能想在这里插手。

于 2009-06-21T01:05:47.473 回答
5

我假设您在问,“Ruby 中的哪些特定技术往往很慢”。

一是对象实例化。如果你正在做大量的事情,你想看看(合理的)减少它的方法,比如使用flyweight 模式,即使内存使用不是问题。在一个库中,我对其进行了重新设计,不再一遍又一遍地创建大量非常相似的对象,我将库的整体速度提高了一倍。

于 2009-06-18T11:05:30.403 回答
4

Steve Dekorte:“用高级语言编写 Mandelbrot 集合计算器就像试图在公共汽车上运行 Indy 500。”

http://www.dekorte.com/blog/blog.cgi?do=item&id=4047

我建议学习各种工具,以便为工作使用正确的工具。使用高级 API 可以有效地进行矩阵转换,该 API 使用算术密集型计算围绕紧密循环。有关将 C 或 C++ 代码嵌入 Ruby 脚本的示例,请参阅 RubyInline gem。

还有一种比 Ruby 慢得多的 Io 语言,但它在 Pixar 中有效地渲染电影,并通过使用 SIMD 加速在矢量算术上优于原始 C。

于 2009-06-18T08:46:59.730 回答
3

根据一些基准测试,Ruby 1.9.1 的速度大约是 PHP 的两倍,并且比 Perl 快一点。

(更新:我的来源是这个截图)。不过,我不知道他的来源是什么。)

红宝石并不慢。旧的 1.8 是,但当前的 Ruby 不是。

于 2009-06-18T08:32:46.233 回答
1

Ruby 很慢,因为它旨在优化程序员的体验,而不是程序的执行时间。缓慢只是该设计决策的一个症状。如果您更喜欢表演而不是娱乐,您可能应该使用不同的语言。Ruby 并不是万能的。

于 2011-04-25T15:53:55.290 回答
0

IMO,动态语言一般都很慢。他们在运行时做一些静态语言在编译时间中所做的事情。

语法检查、解释和类似类型检查、转换。这是不可避免的,因此 ruby​​ 比 c/c++/java 慢,如果我错了,请纠正我。

于 2011-01-28T15:01:13.833 回答