使用 ruby 1.9.2p290(2011-07-09 修订版 32553)[x86_64-linux]
我做了很多分析,我注意到 ruby Fixnum 乘法真的很慢。
通过一些分析,我了解到这是(部分)因为对 Fixnum#* 的每次调用都涉及对 Kernel#kind_of 的 6 次调用。
我知道您可以编写 C 扩展,但这些乘法遍布整个代码。那么,有没有办法在 Ruby 中避免这种开销?
谢谢
最佳答案
我严重怀疑这些测量是否准确,原因如下:
您没有说明您使用的是哪种 Ruby 实现,但
ruby-prof
是一个 Ruby 分析器。它分析了 Ruby 代码。没有我知道Fixnum#*
是 Ruby 代码的 Ruby 实现。在 MRI、YARV、MRuby 和 tinyrb 中是 C 代码,在 Rubinius 中是 C++ 代码,在 MacRuby 中是 Objective-C 代码,在 JRuby 和 XRuby 中是 Java 代码,在 RubyGoLightly 中是 Go 代码,在 IronRuby 和 Ruby 中。 NET 是 C# 代码,在 MagLev 和 SmallRuby 中是 Smalltalk 代码,在 Cardinal 中是 PASM 代码。ruby-prof
可以分析 Ruby 代码,但不能分析 C、C++、Objective-C、Java、C#、Go、Smalltalk 或 PASM。只有 ruby 。因此,它无法分析Fixnum#*
。Fixnum#*
不需要多次检查类。它知道self
是一个Fixnum
,否则调用不会首先分派(dispatch)给Fixnum#*
方法,所以它只需要检查参数。它还需要检查结果是否适合Fixnum
,但它会在内部执行此操作,而不是通过调用kind_of?
(事实上,这不会'甚至有意义:为了能够调用乘法结果的方法,它首先必须构造结果对象,并且为了构造结果对象,它已经必须知道它是否适合是否进入Fixnum
)。它不会通过调用
kind_of?
并遍历整个 Ruby 方法查找和方法分派(dispatch)机制来进行类检查。它是 Ruby 实现的内部函数,它可以访问所有私有(private)内部实现细节,它会直接检查类或调用一些内部解释器函数,而不是 Ruby 方法kind_of?
我检查了各种流行的 Ruby 实现中
Fixnum#*
的实现,但没有发现任何对kind_of?
的调用.不幸的是,您没有说明您使用的是哪种 Ruby 实现。- 鲁比纽斯:
Fixnum::mul
invm/builtin/fixnum.cpp
l. 78–89 - YARV:
fix_mul
innumeric.c
l. 2596–2640 - JRuby:
org.jruby.RubyFixnum.{op_mul, multiplyFixnum, multiplyOther}
insrc/org/jruby/RubyFixnum.java
l. 472–520 (在这里你可以清楚地看到,例如,该方法是如何使用 Java 的instanceof
运算符而不是 Ruby 的kind_of?
方法来检查类的。)
- 鲁比纽斯:
关于ruby - ruby 中更快的 Fixnum 乘法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12081855/