Ruby 2.6のMJITとは何ですか?どのように機能しますか?
Rubyのパフォーマンスはバージョンごとに大幅に向上しており、Ruby開発チームはRubyをさらに高速化するためにあらゆる努力をしています!
これらの取り組みの1つは、3×3プロジェクトです。
目標は?
Ruby3.0はRuby2.0の3倍高速になります 。
このプロジェクトの一部は、この記事のトピックである新しいMJITコンパイラです。
MJITの説明
MJITは「メソッドベースのジャストインタイムコンパイラ」の略です。
それはどういう意味ですか?
RubyはコードをYARV命令にコンパイルします 、これらの命令はRuby仮想マシンによって実行されます。
JITはこれに別のレイヤーを追加します。
頻繁に使用される命令をコンパイルします バイナリコードに変換します。
その結果、コードをより高速に実行する最適化されたバイナリが得られます。
仕組み
MJITがどのように機能して理解を深めるかを調べてみましょう。
Ruby2.6と--jit
でJITを有効にできます オプション。
このように :
ruby --jit app.rb
Ruby 2.6には、JIT固有のオプションのセットが付属しており、それがどのように機能するかを正確に知るのに役立ちます。これらのオプションは、ruby --help
を実行することで確認できます。 。
オプションのリストは次のとおりです
- –jit-wait
- –jit-verbose
- –jit-save-temps
- –jit-max-cache
- –jit-min-calls
この動詞 オプションは良い出発点のように見えます!
--jit-wait
も使用します 、これにより、RubyはJITコードのコンパイルが完了するまで待機してから実行されます。
通常の操作中、JITはワーカースレッドでコードをコンパイルします &それが終了するのを待ちません。
これをテストするために実行できるコマンドは次のとおりです。
ruby --disable-gems --jit --jit-verbose=1 --jit-wait -e "4.times { 123 }"
これは印刷されます :
Successful MJIT finish
まあ、それはあまり面白くないですよね?
JITは何もしていません。
なぜですか?
デフォルトでは、JITはメソッドが5回呼び出されたときにのみ動作します (jit-min-calls
)以上。
これを実行した場合:
ruby --disable-gems --jit --jit-verbose=1 --jit-wait -e "5.times { 123 }"
今、私たちは何か面白いものを手に入れました :
JIT success (32.1ms): block in <main>@-e:1 -> /tmp/_ruby_mjit_p13921u0.c
これは何と言っていますか?
JITは、ブロックを5回呼び出したため、ブロックをコンパイルしました。これにより、次のことがわかります。
- コンパイルにかかった時間 (
32.1ms
)、 - 正確にコンパイルされたもの (
block in <main>
のブロック ) - 生成されたファイル(
/tmp/_ruby_mjit_p13921u0.c
)このコンパイルのソースとして
このファイルは、オブジェクトファイル(.o
)にコンパイルされたCソースコードです。 )&次に共有ライブラリファイル(.so
。
--jit-save-temps
を追加すると、これらのファイルにアクセスできます。 オプション。
ここに例があります :
これは、JITの仕組みについての私の現在の理解です。 :
- メソッド呼び出しをカウントする
- 1つのメソッドが5回呼び出された場合(
jit-min-calls
のデフォルト) )JITをトリガーします - このメソッドの命令を含むCファイルが作成されます(これらはYARV命令ですが、インライン化されています)
- コンパイルはバックグラウンドで行われます(
--jit-wait
を除く) )GCCのような通常のCコンパイラを使用する - コンパイルが完了すると、このメソッドが呼び出されたときに、結果の共有ライブラリファイルが使用されます
これがどれほど効果的か見てみましょう。
MJITのテスト:本当に速いですか?
MJITの目標は、Rubyを高速化することです。
今それをやっているのはどれくらい良いですか?
調べてみましょう!
まず、マイクロベンチマーク:
while | 8倍高速 |
文字列の追加中 | 10%高速 |
乗算中(整数) | 4倍高速 |
乗算中(Bignum) | 20%遅い |
文字列の大文字 | 10%高速 |
2%遅い | |
文字列が一致しますか? | 10%高速 |
10kの乱数を含む配列 | 20%高速 |
パフォーマンスはいたるところにあるようですが、これから推測できることがあります…
MJITはループが本当に好きです!
しかし、より複雑なアプリケーションではどのようにうまくいくのでしょうか?
シンプルなSinatraアプリを試してみましょう :
require 'sinatra' get '/' do "apples, oranges & bananas" end
それほど多くはないように見えるかもしれませんが、この小さなコードは500を超えるさまざまなメソッドを実行します。 JITにやるべき仕事を与えるのに十分です!
具体的には、これはSinatra2.0.4とThin1.7.2です。
次のコマンドでベンチマークを実行できます(apacheベンチ):
ab -c 20 -t 10 https://localhost:4567/
これらは結果です :
これらから、Ruby 2.6は2.5よりも高速であることがわかりますが、 JITを有効にすると、Sinatraが11%遅くなります !
なぜですか?
わかりません。JITによってオーバーヘッドが発生したか、コードが適切に最適化されていないことが原因である可能性があります。
Cプロファイラー(callgrind)を使用したテストでは、JIT最適化コード(以前に発見したコンパイル済みCファイル)の使用はSinatraでは非常に低い( 2%未満)ことがわかりました。 )、しかしそれは非常に高い( 24.22% )8倍の速度ブーストを取得するwhileステートメントの場合。
JITを使用したwhileベンチマークの結果 :
JITを使用したSinatraベンチマークの結果 :
これが理由の一部かもしれません。私はコンパイラの専門家ではないので、これから結論を出すことはできません。
概要
MJITはRuby2.6で利用可能な「ジャストインタイムコンパイラ」であり、--jit
で有効にできます。 国旗。 MJITは有望であり、いくつかの小さなプログラムを高速化できますが、まだやるべきことがたくさんあります!
この記事が気に入ったら、Rubyの友達と共有することを忘れないでください🙂
読んでくれてありがとう。
-
コンピュータ ウイルスとその仕組み
コンピュータウイルスとは? コンピュータ ウイルスは、他のプログラムに付着し、自己複製し、あるコンピュータから別のコンピュータに拡散するマルウェアの一種です。ウイルスがコンピュータに感染すると、自身のコピーを作成し、他のファイルやドキュメントに添付されます。その後、それらのファイルを変更し、拡散を続けます。 ウイルスはコンピュータに密かに感染し、多くの場合、個人のファイルを破壊したり、デバイスを制御したりするように設計されています。コンピュータ ウイルスは自分自身のコピーを作成し、生物学的なウイルスが人から人へと感染するように、デバイスやネットワーク全体に広がります。また、生物学的バージョ
-
Stuxnet:概要と仕組み
Stuxnet とは Stuxnet は、イランの核施設を攻撃するために設計および展開されたコンピューター ワームです。物理インフラに影響を与えたおそらく世界初のサイバー兵器である Stuxnet は、イランの核遠心分離機を標的とし、重要な軍事能力に損害を与えて破壊し、イランの核計画に大きな混乱を引き起こしました。 誰が Stuxnet を作成したのかは公式には明らかにされていませんが、このワームは米国とイスラエル政府によって共同で開発されたと広く理解されています。イランの核兵器計画の進行にますます懸念を抱く両国政府は、核研究開発センターに対する空爆を含む、さまざまな選択肢を検討しました。