web-dev-qa-db-ja.com

Rubyが遅くなる理由は何ですか?

Rubyは特定の点で遅いです。しかし、それのどの部分が最も問題がありますか?

ガベージコレクターはパフォーマンスにどの程度影響しますか?特にOpenGLライブラリを使用している場合、ガベージコレクタを単独で実行するのに数秒かかることがありました。

Rubyで特に遅い行列数学ライブラリを使用しました。Rubyが基本的な数学を実装する方法に問題はありますか?

Rubyに、単に効率的に実装できない動的機能はありますか?もしそうなら、LuaやPython)のような他の言語はこれらの問題をどのように解決しますか?

パフォーマンスを大幅に改善した最近の作業はありますか?

57
Nick Retallack

Rubyは遅いです。しかし、それのどの部分が最も問題がありますか?

柔軟性を考慮して、メソッドの「レイトルックアップ」を実行します。これにより、かなり遅くなります。また、evalを可能にするためにコンテキストごとに変数名を覚えておく必要があるため、フレームとメソッドの呼び出しが遅くなります。また、現在、MRI 1.9にはバイトコードコンパイラ(より優れています)があり、jrubyはそれをJavaバイトコードにコンパイルし、HotSpot JVMを介してコンパイルできます)が、現在は優れたJITコンパイラを欠いていますJITコンパイラですが、最終的には1.9とほぼ同じ速度になります。

ガベージコレクタはパフォーマンスにどの程度影響しますか?特にOpenGLライブラリを使用している場合、ガベージコレクタを単独で実行するのに数秒かかることがありました。

http://www.igvita.com/2009/06/13/profiling-Ruby-with-googles-perftools/ のグラフのいくつかから私はそれが約10%かかると思いますかなり-gc.cのmalloc_limitを増やして再コンパイルすることで、そのヒットを減らすことができます。

Rubyで特に遅い行列数学ライブラリを使用しました。Rubyが基本的な数学を実装する方法に問題はありますか?

Ruby 1.8は、数値クラスを実装した基本的な数学を「実装していません」。Fixnum#+ Fixnum#/のようなものを呼び出しごとに1回呼び出すと、時間がかかりました。 Ruby 1.9は、基本的な数学演算のいくつかをインライン化することで少し不正行為をします。

Rubyに、単に効率的に実装できない動的機能はありますか?もしそうなら、LuaやPython)のような他の言語はこれらの問題をどのように解決しますか?

Evalのようなものは効率的に実装するのは難しいですが、多くの作業を行うことができますが、私は確信しています。 Rubyのキッカーは、誰かのために対応する必要があるということです別のスレッドでクラスの定義を自発的に変更するので、非常に保守的である必要があります。

パフォーマンスを大幅に改善した最近の作業はありますか?

1.9は2倍のスピードアップのようなものです。また、スペース効率も向上します。 JRubyは常に速度の向上に努めています[そしておそらくKRIよりもGCに費やす時間が少ないでしょう]。それに加えて、私が取り組んできたちょっとした趣味以外はあまり気づいていません。また、1.9の文字列は、エンコードのしやすさのために遅くなる場合があることにも注意してください。

70
rogerdpack

Rubyは、ソリューションを迅速に提供するのに非常に適しています。迅速なソリューションを提供するためにはそれほどではありません。解決しようとしている問題の種類によって異なります。 90年代初頭の古いCompuServeMSBASICフォーラムでの議論を思い出しました。Windows開発でどちらが速いかを尋ねられたとき、VBまたはC、通常の答えは「VB、約6月」。

MRI 1.8形式では、Rubyは、ある種の計算集約型タスクの実行に比較的時間がかかります。ほとんどすべてのインタープリター型言語は、ほとんどの主流のコンパイル型言語と比較して、そのように苦しんでいます。

理由はいくつかあります。かなり簡単にアドレス指定できるもの(たとえば、1.8のプリミティブガベージコレクション)とそうでないものがあります。

1.9はいくつかの問題に対処しますが、一般に利用可能になるまでにはおそらくしばらく時間がかかるでしょう。たとえば、JRuby、IronRuby、MagLevなど、既存のランタイムを対象とする他の実装のいくつかは、大幅に高速化される可能性があります。

数学的パフォーマンスに関しては、スループットがかなり遅いのは驚くことではありません。これは、任意精度に対して支払う代償の一部です。繰り返しますが、問題を選択してください。私は70以上の Project Euler の問題をRubyで解決しましたが、実行に1分以上かかる解決策はほとんどありません。実行するのにどれくらいの速さが必要で、どれくらい早く必要ですか?

11
Mike Woodhouse

最も問題のある部分は「全員」です。

その「全員」が実際にその言語を使用していなかった場合のボーナスポイント。

真剣に、1.9ははるかに高速で、現在はpythonと同等であり、jrubyはjythonよりも高速です。

ガベージコレクターはいたるところにあります。たとえば、Javaには1つあり、動的メモリ処理ではC++よりも高速です。Rubyは数値計算には適していませんが、言語はほとんどありません。したがって、プログラムに計算集約型の部分が任意の言語で含まれている場合は、Cで書き直す方がよいでしょう(Javaはプリミティブ型であるため数学は高速ですが、かなりの費用がかかります。これらは明らかに、言語)。

動的機能については、高速ではありませんが、静的言語でそれらを使用しないコードはさらに遅くなる可能性があります。たとえば、Javaは、DSLを使用するRubyの代わりにXML構成を使用します。また、XMLの解析にはコストがかかるため、処理が遅くなる可能性があります。

9
alamar

うーん-私は数年前にRubyパフォーマンスでバレルをこすったプロジェクトに取り組みましたが、それ以来あまり変わっていないかわかりません。今は注意が必要です-知っておく必要があります特定のことをしないでください。率直に言って、ゲーム/リアルタイムアプリケーションはその1つです(OpenGLについて言及しているため)。

インタラクティブなパフォーマンスを殺した原因はガベージコレクターです-ここで他の人はJavaや他の環境にもガベージコレクションがありますが、Rubyは世界を止めなければなりません実行するには、つまり、プログラムの実行を停止し、すべてのレジスタとメモリポインタを最初からスキャンし、まだ使用中のメモリにマークを付け、残りを解放する必要があります。プロセスは次のことができます。これが発生している間は中断されません。お気づきかもしれませんが、数百ミリ秒かかる場合があります。

その実行の頻度と長さは、作成および破棄するオブジェクトの数に比例しますが、完全に無効にしない限り、制御することはできません。私の経験では、Rubyアニメーションループをスムーズにするためのいくつかの不十分な戦略がありました:

  • GC.disable/GC.enableは、重要なアニメーションループの周りにあり、日和見的なGC.startは、害を及ぼすことができないときに強制的に実行します。 (当時の私のターゲットプラットフォームは64MBのWindows NTマシンであったため、システムのメモリが不足することがありました。しかし、基本的には悪い考えです。これを行う前に必要なメモリ量を事前に計算できない限り、 'メモリ不足のリスクがあります)
  • 作成するオブジェクトの数を減らして、GCの作業を減らします(実行の頻度/長さを減らします)
  • アニメーションループをCで書き直します(警官ですが、私が使用したものです!)

最近では、JRubyがJavaのより洗練されたガベージコレクターに依存していると思うので、JRubyが代替ランタイムとして機能するかどうかも確認するでしょう。

私が見つけた他の主要なパフォーマンスの問題は、TFTPサーバーをRubyしばらく前に書き込もうとしたときの、基本的なI/Oです(ええ、パフォーマンスが重要なプロジェクトに最適な言語をすべて選択します)あるUDPパケットを別のUDPパケットで単純に応答し、ファイルの次の部分を含む、最も単純で最もタイトなループは、ストックCバージョンよりも約20倍遅いはずです。いくつかの改善があったのではないかと思います。低レベルのIO(sysreadなど)の使用に基づいてそこを作成しますが、速度が遅いのは、低レベルのバイトデータタイプがないという事実だけかもしれません-小さな読み取りはすべてにコピーされます文字列。これは単なる推測ですが、私はこのプロジェクトをこれ以上進めませんでしたが、きびきびとしたI/Oに依存することを警告しました。

最近の主な速度の向上は、ここでは完全に最新ではありませんが、仮想マシンの実装が1.9に再実行され、コードの実行が高速化されたことです。ただし、 GCは変更されていないと思います 、I/Oの面で新しいことは何もないと確信しています。しかし、私はBreading-Edge Rubyについて完全に最新ではないので、他の誰かがここにチップを入れたいと思うかもしれません。

8
Matthew Bloch

スティーブ・デコルテ:「マンデルブロ集合計算機を高級言語で書くことは、バスでインディ500を走らせようとするようなものです。」

http://www.dekorte.com/blog/blog.cgi?do=item&id=4047

仕事に適したツールを使用するために、さまざまなツールを学ぶことをお勧めします。行列変換の実行は、算術演算を多用する計算でタイトなループをラップアラウンドする高レベルAPIを使用して効率的に実行できます。 CまたはC++コードをRubyスクリプトに埋め込む例については、RubyInlinegemを参照してください。

Rubyよりもはるかに遅いIo言語もありますが、Pixarで映画を効率的にレンダリングし、SIMDアクセラレーションを使用することでベクトル演算で生のCよりも優れています。

4
Oleg Andreev

「Rubyのどの特定のテクニックが遅い傾向があるか」とあなたが尋ねていると思います。

1つはオブジェクトのインスタンス化です。大量に実行している場合は、メモリ使用量に問題がない場合でも、 flyweight pattern を使用するなど、それを減らす(合理的な)方法を検討する必要があります。非常によく似たオブジェクトを何度も作成しないように作り直した1つのライブラリでは、ライブラリの全体的な速度が2倍になりました。

4
Curt J. Sampson

いくつかのベンチマークによると、Ruby 1.9.1はPHPの約2倍、Perlよりも少し高速です。

(更新:私のソースは thisscreenshot )です。しかし、彼のソースが何であるかはわかりません。)

Rubyは遅くはありません。古い1.8はそうですが、現在のRubyはそうではありません。

3
August Lilleaas

Rubyは、プログラムの実行時間ではなく、プログラマーのエクスペリエンスを最適化するように設計されているため、低速です。速度低下は、その設計上の決定の単なる症状です。楽しみよりもパフォーマンスを好む場合は、おそらく別の言語を使用する必要があります。 Rubyは万能ではありません。

2
Joe Flynn

IMO、動的言語はすべて一般的に遅いです。それらは、静的言語がコンパイル時に行うのと同じことを実行時に行います。

構文チェック、解釈、およびLike型チェック、変換。これは避けられないので、Rubyはc/c ++/Javaよりも遅いので、間違っている場合は訂正してください。

1
c2h2