使用紅寶石1.9.2p290(2011-07-09修訂版32553)[x86_64-linux]更快在紅寶石Fixnum乘法?
我一直在做很多分析,它引起了我的注意,ruby Fixnum乘法非常慢。
通過一些分析,我瞭解到這是(部分),因爲每次調用Fixnum#*都涉及到6個調用Kernel#kind_of。
我知道你可以編寫C擴展,但是這些乘法會遍及整個代碼。那麼,有沒有辦法避免Ruby內部的這種開銷?
感謝
使用紅寶石1.9.2p290(2011-07-09修訂版32553)[x86_64-linux]更快在紅寶石Fixnum乘法?
我一直在做很多分析,它引起了我的注意,ruby Fixnum乘法非常慢。
通過一些分析,我瞭解到這是(部分),因爲每次調用Fixnum#*都涉及到6個調用Kernel#kind_of。
我知道你可以編寫C擴展,但是這些乘法會遍及整個代碼。那麼,有沒有辦法避免Ruby內部的這種開銷?
感謝
我嚴重懷疑,這些測量結果是準確的,有以下幾個原因:
你沒有說明您正在使用的紅寶石的實施,但ruby-prof
是一個Ruby分析器。它描述Ruby代碼。我不知道Ruby的執行情況,其中Fixnum#*
是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
,因爲否則該調用首先不會被調度到Fixnum#*
方法,因此它只需要檢查參數。它還需要檢查結果是否適合Fixnum
,但它會在內部完成,而不是通過調用kind_of?
(事實上,這甚至沒有意義:爲了能夠調用方法根據乘法的結果,它首先必須構造結果對象,並且爲了構造結果對象,它將不得不知道它是否適合於Fixnum
)。
它不會通過調用kind_of?
來進行類檢查,並通過整個Ruby方法查找和方法調度機制。這是Ruby實現的內部功能,它可以訪問所有的私有內部實現細節,它只是直接檢查類或調用一些內部翻譯功能,而不是Ruby的方法kind_of?
我檢查的Fixnum#*
的實施各種流行的Ruby實現,並沒有發現任何調用kind_of?
。不幸的是,你沒有說明你正在使用哪個Ruby實現。
Fixnum::mul
in vm/builtin/fixnum.cpp
l. 78–89fix_mul
in numeric.c
l. 2596–2640org.jruby.RubyFixnum.{op_mul, multiplyFixnum, multiplyOther}
in src/org/jruby/RubyFixnum.java
l. 472–520(在這裏,你可以清楚地看到,例如,該方法是如何使用Java instanceof
操盤Ruby的kind_of?
方法來檢查類。)感謝您的回覆。我當然可能是錯的。這裏就是我看到我的探查輸出: '23.52%9.49%5.17 2.08 0.00 3.08 808533#長整數*'' 2.27 2.27 0.00 0.00五百三十五萬五千五百三十四分之四百八十五萬一千一百九十八內核#kind_of' 我不知道,如果你熟悉ruby-prof圖形輸出,但方法名稱下方的行是從該方法調用的方法。 我不知道我在使用什麼實現。它要麼來自Ubuntu,要麼來自apt-get。你知道我能找到什麼嗎? – user844942
你說得對,順便說一句。如果你對發生的事情感到好奇,看看我的答案。 – user844942
那麼,我想我想通了。我正在使用GSL庫,並且它看起來修補了Fixnum#*代碼,您可以在這裏看到:https://github.com/romanbsd/rb-gsl/blob/master/lib/gsl/oper.rb#L15
此代碼包括...等待它... 6個調用內核#kind_of?在一個大的醇'或'聲明。
我不會假裝完全理解它是如何工作的或它爲什麼會發生,但代碼路徑與探查器輸出完全匹配。
這很有趣。你用什麼來分析代碼?我會猜想本地Ruby乘法相對有效。 –
@BlakeTaylor我正在使用ruby-prof – user844942