使用 ruby 1.9.2p290(2011-07-09 修订版 32553)[x86_64-linux]
我一直在做很多分析,我注意到 ruby Fixnum 乘法真的很慢。
通过一些分析,我了解到这是(部分)因为对 Fixnum#* 的每次调用都涉及对 Kernel#kind_of 的 6 次调用。
我知道你可以编写 C 扩展,但这些乘法分布在整个代码中。那么,有没有办法在 Ruby 中避免这种开销呢?
谢谢
使用 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。只有红宝石。因此,它根本无法配置文件Fixnum#*
。
无需Fixnum#*
多次检查课程。它知道那self
是 a Fixnum
,否则调用不会一开始就分派给Fixnum#*
方法,所以它只需要检查参数。它还需要检查结果是否适合a Fixnum
,但它会在内部完成,而不是通过调用kind_of?
(事实上,这甚至没有意义:为了能够在乘法的结果,它首先必须构造结果对象,并且为了构造结果对象,它必须知道它是否适合a Fixnum
)。
它不会通过调用kind_of?
和遍历整个 Ruby 方法查找和方法分派机制来进行类检查。它是 Ruby 实现的内部函数,它可以访问所有私有内部实现细节,它只会直接检查类或调用一些内部解释器函数,而不是 Ruby 方法kind_of?
我检查了Fixnum#*
各种流行的 Ruby 实现中的实现,没有发现任何对kind_of?
. 不幸的是,您没有说明您使用的是哪个 Ruby 实现。
Fixnum::mul
在vm/builtin/fixnum.cpp
l。78–89fix_mul
在numeric.c
l。2596–2640org.jruby.RubyFixnum.{op_mul, multiplyFixnum, multiplyOther}
在src/org/jruby/RubyFixnum.java
l。472–520(在这里你可以清楚地看到,例如,方法如何使用 Javainstanceof
运算符而不是 Ruby 的kind_of?
方法来检查类。)嗯,我想我想通了。我正在使用 GSL libray,它似乎使用您可以在此处看到的代码修补了 Fixnum#*:https ://github.com/romanbsd/rb-gsl/blob/master/lib/gsl/oper.rb# L15
此代码包括...等待它... 6 调用 Kernel#kind_of?在一个大的“或”声明中。
我不会假装完全理解它的工作原理或发生原因,但代码路径与分析器输出完美匹配。