5

使用 ruby​​ 1.9.2p290(2011-07-09 修订版 32553)[x86_64-linux]

我一直在做很多分析,我注意到 ruby​​ Fixnum 乘法真的很慢。

通过一些分析,我了解到这是(部分)因为对 Fixnum#* 的每次调用都涉及对 Kernel#kind_of 的 6 次调用

我知道你可以编写 C 扩展,但这些乘法分布在整个代码中。那么,有没有办法在 Ruby 中避免这种开销呢?

谢谢

4

2 回答 2

5

我严重怀疑这些测量结果是否准确,原因如下:

  1. 您没有说明您使用的是哪个 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#*

  2. 无需Fixnum#*多次检查课程。它知道那self是 a Fixnum,否则调用不会一开始就分派给Fixnum#*方法,所以它只需要检查参数。它还需要检查结果是否适合a Fixnum,但它会在内部完成,而不是通过调用kind_of?(事实上,这甚至没有意义:为了能够在乘法的结果,它首先必须构造结果对象,并且为了构造结果对象,它必须知道它是否适合a Fixnum)。

  3. 它不会通过调用kind_of?和遍历整个 Ruby 方法查找和方法分派机制来进行类检查。它是 Ruby 实现的内部函数,它可以访问所有私有内部实现细节,它只会直接检查类或调用一些内部解释器函数,而不是 Ruby 方法kind_of?

  4. 我检查了Fixnum#*各种流行的 Ruby 实现中的实现,没有发现任何kind_of?. 不幸的是,您没有说明您使用的是哪个 Ruby 实现。

于 2012-08-23T00:55:25.467 回答
2

嗯,我想我想通了。我正在使用 GSL libray,它似乎使用您可以在此处看到的代码修补了 Fixnum#*:https ://github.com/romanbsd/rb-gsl/blob/master/lib/gsl/oper.rb# L15

此代码包括...等待它... 6 调用 Kernel#kind_of?在一个大的“或”声明中。

我不会假装完全理解它的工作原理或发生原因,但代码路径与分析器输出完美匹配。

于 2012-08-23T15:45:29.647 回答