是什么让 Ruby 变慢了?

发布于 2024-07-24 16:36:07 字数 1438 浏览 5 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

箹锭⒈辈孓 2024-07-31 16:36:07

Ruby 很慢。 但其中哪些部分最有问题呢?

它对方法进行“后期查找”,以实现灵活性。 这会大大减慢速度。 它还必须记住每个上下文的变量名称以允许 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%,这相当多了——你可以通过增加 malloc_limit 来减少这种影响gc.c 并重新编译。

我在 Ruby 中使用了矩阵数学库,但速度特别慢。 ruby 实现基本数学的方式有问题吗?

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

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

像 eval 这样的事情很难有效地实施,尽管我确信可以做很多工作。 Ruby 的优点在于它必须适应另一个线程中的某人自发地更改类的定义,因此它必须非常保守。

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

1.9 相当于 2 倍加速。 它还更节省空间。 JRuby 不断尝试提高速度 [并且可能比 KRI 在 GC 上花费的时间更少]。 除此之外,除了我一直在做的一些小爱好之外,我不知道太多。 另请注意,由于编码友好性,1.9 的字符串有时会变慢。

Ruby is slow. But what parts of it are the most problematic?

It does "late lookup" for methods, to allow for flexibility. This slows it down quite a bit. It also has to remember variable names per context to allow for eval, so its frames and method calls are slower. Also it lacks a good JIT compiler currently, though MRI 1.9 has a bytecode compiler (which is better), and jruby compiles it down to java bytecode, which then (can) compile via the HotSpot JVM's JIT compiler, but it ends up being about the same speed as 1.9.

How much does the garbage collector effect performance? I know I've had times when running the garbage collector alone took several seconds, especially when working with OpenGL libraries.

from some of the graphs at http://www.igvita.com/2009/06/13/profiling-ruby-with-googles-perftools/ I'd say it takes about 10% which is quite a bit--you can decrease that hit by increasing the malloc_limit in gc.c and recompiling.

I've used matrix math libraries with Ruby that were particularly slow. Is there an issue with how ruby implements basic math?

Ruby 1.8 "didn't" implement basic math it implemented Numeric classes and you'd call things like Fixnum#+ Fixnum#/ once per call--which was slow. Ruby 1.9 cheats a bit by inlining some of the basic math ops.

Are there any dynamic features in Ruby that simply cannot be implemented efficiently? If so, how do other languages like Lua and Python solve these problems?

Things like eval are hard to implement efficiently, though much work can be done, I'm sure. The kicker for Ruby is that it has to accomodate for somebody in another thread changing the definition of a class spontaneously, so it has to be very conservative.

Has there been recent work that has significantly improved performance?

1.9 is like a 2x speedup. It's also more space efficient. JRuby is constantly trying to improve speed-wise [and probably spends less time in the GC than KRI]. Besides that I'm not aware of much except little hobby things I've been working on. Note also that 1.9's strings are at times slower because of encoding friendliness.

你不是我要的菜∠ 2024-07-31 16:36:07

Ruby 非常适合快速交付解决方案。 对于提供快速解决方案来说则不然。 这取决于您想要解决什么类型的问题。 我想起了 90 年代初旧的 CompuServe MSBASIC 论坛上的讨论:当被问及 Windows 开发,VB 或 C 哪个更快时,通常的答案是“VB,大约 6 个月”。

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

原因有几个:有些相当容易解决(例如 1.8 中的原始垃圾收集),有些则不太容易解决。

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

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

Ruby is very good for delivering solutions quickly. Less so for delivering quick solutions. It depends what kind of problem you're trying to solve. I'm reminded of the discussions on the old CompuServe MSBASIC forum in the early 90s: when asked which was faster for Windows development, VB or C, the usual answer was "VB, by about 6 months".

In its MRI 1.8 form, Ruby is - relatively - slow to perform some types of computationally-intensive tasks. Pretty much any interpreted language suffers in that way in comparison to most mainstream compiled languages.

The reasons are several: some fairly easily addressable (the primitive garbage collection in 1.8, for example), some less so.

1.9 addresses some of the issues, although it's probably going to be some time before it becomes generally available. Some of the other implementation that target pre-existing runtimes, JRuby, IronRuby, MagLev for example, have the potential to be significantly quicker.

Regarding mathematical performance, I wouldn't be surprised to see fairly slow throughput: it's part of the price you pay for arbitrary precision. Again, pick your problem. I've solved 70+ of the Project Euler problems in Ruby with almost no solution taking more than a mintue to run. How fast do you need it to run and how soon do you need it?

葬花如无物 2024-07-31 16:36:07

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

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

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

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

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

The most problematic part is "everyone".

Bonus points if that "everyone" didn't really use the language, ever.

Seriously, 1.9 is much faster and now is on par with python, and jruby is faster than jython.

Garbage collectors are everywhere; for example, Java has one, and it's faster than C++ on dynamic memory handling. Ruby isn't suited well for number crunching; but few languages are, so if you have computational-intensive parts in your program in any language, you better rewrite them in C (Java is fast with math due to its primitive types, but it paid dearly for them, they're clearly #1 in ugliest parts of the language).

As for dynamic features: they aren't fast, but code without them in static languages can be even slower; for example, java would use a XML config instead of Ruby using a DSL; and it would likely be SLOWER since XML parsing is costly.

昵称有卵用 2024-07-31 16:36:07

嗯 - 几年前我参与了一个项目,在那里我用 Ruby 性能刮擦了桶,我不确定从那以后有什么变化。 现在买者自负——你必须知道不要做某些事情,坦率地说,游戏/实时应用程序就是其中之一(因为你提到了 OpenGL)。

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

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

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

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

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

最近速度的主要提升是 1.9 版本中虚拟机实现的重做,从而提高了代码执行速度,尽管我在这里还没有完全了解最新情况。 但是 我不认为 GC已经改变了,而且我很确定 I/O 方面没有什么新东西。 但我对前沿 Ruby 还不太了解,所以其他人可能想在这里参与进来。

Hmm - I worked on a project a few years ago where I scraped the barrel with Ruby performance, and I'm not sure much has changed since. Right now it's caveat emptor - you have to know not to do certain things, and frankly games / realtime applications would be one of them (since you mention OpenGL).

The culprit for killing interactive performance is the garbage collector - others here mention that Java and other environments have garbage collection too, but Ruby's has to stop the world to run. That is to say, it has to stop running your program, scan through every register and memory pointer from scratch, mark the memory that's still in use, and free the rest. The process can't be interrupted while this happens, and as you might have noticed, it can take hundreds of milliseconds.

Its frequency and length of execution is proportional to the number of objects you create and destroy, but unless you disable it altogether, you have no control. My experience was there were several unsatisfactory strategies to smooth out my Ruby animation loop:

  • GC.disable / GC.enable around critical animation loops and maybe an opportunistic GC.start to force it to go when it can't do any harm. (because my target platform at the time was a 64MB Windows NT machine, this caused the system to run out of memory occasionally. But fundamentally it's a bad idea - unless you can pre-calculate how much memory you might need before doing this, you're risking memory exhaustion)
  • Reduce the number of objects you create so the GC has less work to do (reduces the frequency / length of its execution)
  • Rewrite your animation loop in C (a cop-out, but the one I went with!)

These days I would probably also see if JRuby would work as an alternative runtime, as I believe it relies on Java's more sophisticated garbage collector.

The other major performance issue I've found is basic I/O when trying to write a TFTP server in Ruby a while back (yeah I pick all the best languages for my performance-critical projects this was was just an experiment). The absolute simplest tightest loop to simply respond to one UDP packet with another, contaning the next piece of a file, must have been about 20x slower than the stock C version. I suspect there might have been some improvements to make there based around using low-level IO (sysread etc.) but the slowness might just be in the fact there is no low-level byte data type - every little read is copied out into a String. This is just speculation though, I didn't take this project much further but it warned me off relying on snappy I/O.

The main speed recent increase that has gone on, though I'm not fully up-to-date here, is that the virtual machine implementation was redone for 1.9, resulting in faster code execution. However I don't think the GC has changed, and I'm pretty sure there's nothing new on the I/O front. But I'm not fully up-to-date on bleeding-edge Ruby so someone else might want to chip in here.

Spring初心 2024-07-31 16:36:07

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

一是对象实例化。 如果您要做大量的事情,您需要寻找(合理的)方法来减少这种情况,例如使用 享元模式,即使内存使用不是问题。 在一个库中,我对其进行了重新设计,以免一遍又一遍地创建大量非常相似的对象,我将库的整体速度提高了一倍。

I assume that you're asking, "what particular techniques in Ruby tend to be slow."

One is object instantiation. If you are doing large amounts of it, you want to look at (reasonable) ways of reducing that, such as using the flyweight pattern, even if memory usage is not a problem. In one library where I reworked it not to be creating a lot of very similar objects over and over again, I doubled the overall speed of the library.

演多会厌 2024-07-31 16:36:07

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

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

我建议学习各种工具,以便使用正确的工具来完成工作。 使用高级 API 可以有效地完成矩阵变换,该 API 通过算术密集型计算包裹紧循环。 有关将 C 或 C++ 代码嵌入到 Ruby 脚本中的示例,请参阅 RubyInline gem。

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

Steve Dekorte: "Writing a Mandelbrot set calculator in a high level language is like trying to run the Indy 500 in a bus."

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

I recommend to learn various tools in order to use the right tool for the job. Doing matrix transformations could be done efficiently using high-level API which wraps around tight loops with arithmetic-intensive computations. See RubyInline gem for an example of embedding C or C++ code into Ruby script.

There is also Io language which is much slower than Ruby, but it efficiently renders movies in Pixar and outperforms raw C on vector arithmetics by using SIMD acceleration.

梦里人 2024-07-31 16:36:07

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

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

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

Ruby 1.9.1 is about twice as fast as PHP, and a little bit faster than Perl, according to some benchmarks.

(Update: My source is this (screenshot). I don't know what his source is, though.)

Ruby is not slow. The old 1.8 is, but the current Ruby isn't.

白云不回头 2024-07-31 16:36:07

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

Ruby is slow because it was designed to optimize the programmers experience, not the program's execution time. Slowness is just a symptom of that design decision. If you would prefer performance to pleasure, you should probably use a different language. Ruby's not for everything.

沙沙粒小 2024-07-31 16:36:07

IMO,动态语言总体来说都很慢。 它们在运行时执行静态语言在编译时执行的操作。

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

IMO, dynamic languages are all slow in general. They do something in runtime that static languages do in compiling time.

Syntax Check, Interpreting and Like type checking, converting. this is inevitable, therefore ruby is slower than c/c++/java, correct me if I am wrong.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文