アカウント名:
パスワード:
#これって、java.lang.reflect.FieldやMethodといったObjectを後生大事にメモリ上に保持しておく、という意味ですよねよね?
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
アレゲは一日にしてならず -- アレゲ見習い
次の10年で (スコア:0)
本当に速度(スループット性能)を求めるなら (スコア:3, 興味深い)
Ruby のメモリ管理に関するまつもと氏の講演を聞きました。
その話では、Ruby の実装は移植性を重視。速度を求めていないようでした。
例えば、オブジェクトは 5ワード固定で、そこからはみ出すクラスや
文字列型の実体部分は malloc/free してオブジェクトにリンクするそうです。
つまり、オブジェクトヘッダーとオブジェクトボディが別々に管理されている
格好ですな。ヘッダーは固定長(5ワード)で、ボディは必要に合わせて
「ヒープ」外に確保すると。
スループット性能を本当に重視するのであれば、
その方向に性能を伸ばすにはどうやればいいか分かっている人が、
フルスクラッチで実装し直せば それだけで速くなると思います。
後は JIT コンパイラ次第で Java と同じ速度は出ると思います。
p.s.
私は一時 Ruby のソースを Java のバイトコードに変換しようと沈思黙考しました。
ただ動けばいいというレベルの変換をすることは可能なのですが、
ちゃんとした速度を出すためには色々最適化が必要になります。
a. オブジェクトのうち可能なものはスタック割り付けに
b. メソッド呼び出しを高速化
a. に関しては、数値型オブジェクトを対象にコード解析(つまり、エスケープ解析)を行えば、かなりの部分が Java の primitive 型にできると踏んでいます。
問題は b. で、静的に VTBL が作れる C++ や、クラスロード時に VTBL が作れる Java と違って、Ruby のメソッド呼び出しは完全に late-binding で、その名前のメソッドがあるかどうかの名前解決も実行時にやりますよね。
つまり、Ruby のメソッド呼び出しを ナイーブに Java のバイトコードで実現しようとすると、全部 reflection 経由のメソッド呼び出しにする必要があります。これは大変に重い処理ですので、ここから通常のメソッド呼び出しに変換したいのです。
これ、.rb → .class コンパイラレベルで何かうまい最適かはありますかね?
# って 書いてますけど、
# JavaVM 側が reflection 経由のメソッド呼び出し → 通常のメソッド呼び出し →
# de-virtualization と最適化するのが 1 番ですね。。
コンタミは発見の母
Re:本当に速度(スループット性能)を求めるなら (スコア:1)
>メソッド呼び出しにする必要があります。これは大変に重い処理ですので、ここから通常のメソッド呼び出しに変換したいのです
俺も全然判ってないんですが、
以前CMPもどきを車輪再開発したとき(笑)にちょっと考えたんだけど、そのとき見つけたネタとして、
「 照合にキャッシュを使用する限りリフレクションは非常に高速です。 [borland.co.jp]」
なんてな話もあるようで、これってもしかして、反論(?)として意味有りでしょうか?あんまり関係ないかな…
#これって、java.lang.reflect.FieldやMethodといったObjectを後生大事にメモリ上に保持しておく、という意味ですよねよね?
Re:本当に速度(スループット性能)を求めるなら (スコア:1)
そうです。
例を#268334 [srad.jp]に挙げましたが、この例に沿って言うと Borland の言うキャッシュは m をどこかに保存しておいて再利用しようというものです。
この方法の問題点は m をどこに引っかけるかで、
ぱっと考えてメソッドコード中に埋め込むか、オブジェクトに埋め込むことになると思います。
メソッドコードに埋め込む場合、aSong.to_s をキャッシュすると
static Object cached_object ; // C 的な関数ローカルの static のイメージ
static Method cached_method ;
if( cached_object != aSong ){
// cache misshit
Method m = aSong.getClass().getMethod( "to_s", /* parameter types */ );
cached_object = aSong ;
cached_method = m;
}
cached_method.invoke( aSong, null ); // 呼び出し
オブジェクト(ruby.lang.Object) に埋め込む場合、
class ruby.lang.Object { // 根本のクラスに追加
// ...
int cached_line ;
Method cached_method ;
}
if( aSong.cached_line != 987654321 ){ // ソース行に対応した unique な番号
// cache misshit
aSong.cached_line = 987654321;
aSong.cached_method = aSong.getClass().getMethod( "to_s", /* parameter types */ );
}
aSong.cached_method.invoke( aSong.null ); // 呼び出し
ここまで書いて何なんですけど、速くなりそうにない変換っすね (;_;
コンタミは発見の母
Re:本当に速度(スループット性能)を求めるなら (スコア:1)
// Ruby のソース
class Song
def to_s
// ...
end
end
aSong = Song.new
aSong.to_s
をナイーブに Java に変換すると以下のようになります。
// Java のソース
class Song extends ruby.lang.Object {
ruby.lang.ReturnValue to_s(ruby.lang.Parameters parms){
//
}
}
aSong = new Song();
Method m = aSong.getClass().getMethod( "to_s", /* parameter types */ );
m.invoke( aSong, null );
このメソッド呼び出しの部分を
aSong.to_s( /* ? */ )
の形にできるのであれば、Ruby → Java に変換することで
パフォーマンスの向上が期待できると思います。
コンタミは発見の母