マジックコメントでRubyの最適化をする Ruby Optimization with One Magic Comment
Ruby Optimization with One Magic Comment
ソフトウェアのパフォーマンスの最適化は簡単です:少ないことをする方法を見つける。 Rubyは遅いという評判があります。その印象は10年前からですが、主要な犯罪者の1人はガベージコレクタです。 これは、gabageを少なくしてRubyのスピードを上げることができますか?もちろん!
文字列の入門
Rubyは、すべての文字列が変更可能であるという不幸なデフォルト文法を持っています:
string = "" string << "mike"
これは2つの文字列 ""と "mike"を割り当てます。最初の空文字列は、「mike」を含むように変更されます。 しかし、文字列の変異は非常にまれであり、より一般的なのは次のようなものです:
HASH = { "mike": 123 } def getmike HASH["mike"] # unnecessary garbage here! end
getmikeを呼び出すたびに "mike"の新しいコピーが割り当てられ、すぐにガベージとして破棄されますが、 RubyはStringをHash#[]内で変更されるメソッドの引数として扱うだけなので必要です。とても無駄です!
Freeze! Rubyは、割り当てを最小限に抑えるために、何年も前にFreezeの概念を導入しました。オブジェクトのフリーズを呼び出すと、 Rubyはそれを不変として扱うように指示します。 Rubyは "mike"を定数として扱うことができます:
def getmike HASH["mike".freeze] end
Magic Comments! Ruby 2.3では、非常に良いオプションが導入されました。各Rubyファイルは文字列を不変として選択できます。 つまり、ファイル内のすべての文字列が自動的にフリーズし、ファイルの先頭に簡単な魔法のコメントが付きます。 これは、 "mike"に追加のStringを割り当てません。
# frozen_string_literal: true HASH = { "mike": 123 } def getmike HASH["mike"] end
実世界 数年前、ガーベジコレクタへの影響を最小限に抑え、パフォーマンスを最大化するために、Sidekiqに多くのフリーズコールを追加しました。 先週、これらの呼び出しをすべて削除し、すべてのRubyファイルにfrozen_string_literalコメントを追加しました。 この効果を確認するために、Sidekiqのベンチマークスクリプトを使ってGC.disableを追加し、RSSが成長するのを見て、 frozen_string_literalの実験を行った。 Rubyでは、フラグ付きの機能を有効または無効にすることができます。 無効
$ RUBYOPT=--disable=frozen-string-literal bundle exec bin/sidekiqload Created 30000 jobs RSS: 105852 Pending: 25749 RSS: 178880 Pending: 21514 RSS: 252804 Pending: 17306 RSS: 326824 Pending: 12987 RSS: 399268 Pending: 8810 RSS: 472620 Pending: 4618 RSS: 547968 Pending: 319 RSS: 553568 Pending: 0 Done
有効
$ RUBYOPT=--enable=frozen-string-literal bundle exec bin/sidekiqload Created 30000 jobs RSS: 105824 Pending: 25687 RSS: 174948 Pending: 21700 RSS: 245448 Pending: 17669 RSS: 316848 Pending: 13559 RSS: 388544 Pending: 9447 RSS: 456704 Pending: 5288 RSS: 450552 Pending: 1160 RSS: 457536 Pending: 0 Done
rozen_string_literalは、生成されたガベージを〜100MBまたは〜20%削減します! 1行のコメントを追加してパフォーマンスを向上させます。
結論 gemの作者:# frozen_string_literal: true:gemのすべてのRubyファイルのトップに追加してください。 これは、文字列の突然変異を使用しない限り、すべてのユーザーに無料のパフォーマンス向上をもたらします。
Notes