13

Ruby on Rails アプリケーションがあります。私は NewRelic ポータルで Apdex の減少を調査しており、GC の実行に平均で 250 ~ 320 ミリ秒の時間が費やされていることを確認しています。これは非常に不安な数字です。以下にスクリーンショットを含めました。

私のRubyバージョンは次のとおりです。

ruby 1.9.3p194 (2012-04-20 リビジョン 35410) [x86_64-linux]

これを調整するための提案は理想的です。この数値は大幅に低くなるはずです。

ここに画像の説明を入力

4

4 に答える 4

10

GC を頻繁に実行しているため、GC に多くの時間を費やしています。Ruby はデフォルトで、大きなアプリではなく、小さなスクリプトに適した GC パラメータを設定します。次の環境パラメーターを設定してアプリを起動してみてください。

RUBY_HEAP_MIN_SLOTS=800000
RUBY_FREE_MIN=100000
RUBY_GC_MALLOC_LIMIT=79000000

これが行うことは、初期ヒープ割り当てサイズを増やし、GC 番号をパディングして、あまり頻繁に実行されないようにすることです。これにより、アプリが使用する RAM が少し増えますが、GC に費やされる時間が大幅に短縮されます。デフォルト設定では、リクエストごとに GC を複数回実行する可能性があります。理想的には、数回のリクエストごとに1回実行する必要があります(または、Unicornの OOB::GCなどのリクエスト間でさらに良い)。

これらは私のアプリの GC 設定です。アプリが適切な設定を見つけるのに最も適しているように、それらを上下に微調整する必要があります。GC をそれほど頻繁に実行せず、過度のメモリ使用量を持たない中間点を狙っています。ただし、これは各アプリに固有であるため、これらの正確な設定がどうあるべきかについて私が与えることができるボイラープレートのアドバイスはありません. デフォルト (10,000 スロット、1.8 倍の成長率) から増やすと、すぐに影響が出るはずです。現在の状況に最適なように、そこから上下に微調整できます。

これらのパラメーターの完全なまとめはこちら、詳細はこちらです。これらの投稿は REE 1.8.7 向けに書かれていますが、Ruby 1.9.2+ にも適用できます。

これらはかなり極端な数値であるため、必要以上に多くの RAM を割り当てる原因となっている何かをアプリで実行している可能性があります。熱心な割り当て。ただし、GC 環境変数は、どのような場合でも状況のトリアージに役立つはずです。

于 2012-11-18T19:24:00.820 に答える
0

誤って不要なオブジェクトを作成していないと仮定すると、(JRubyを使用する以外に)1つのハック/解決策は、応答の送信が終了した後にGCを強制することだと聞きました。このようにすると、一時停止が大きくなりますが、リクエストのコンシューマーには表示されません。あなたがこのような複数の一時停止を見ている非常に多くのゴミを持っているなら、あなたは運が悪いかもしれません。

このトリックは、ニーズに合わせて機能する場合と機能しない場合があります。

-MRIGCの問題を抱えている人々と話すJRubyの男:)

于 2012-11-25T17:32:39.473 に答える
0

この小さなハックもあり、うまくいくかもしれません。しかし、より大きなアプリケーションは、リクエストごとにワーカーを殺すほど大量のメモリを割り当てる傾向があります:-/

于 2012-11-18T23:42:16.713 に答える
0

コードがオブジェクトを割り当てている場所とその数を調べるには、割り当てトレーサーを使用する必要があります。過去に使用memprofして素晴らしい結果を得ました...大きな欠点は、Ruby 1.8でしか機能しないことです(コードが1.8.7と互換性があることを願っています)。

アプリケーションを Ruby 1.8.7 で実行できる場合は、「memprof」gem をインストールします。

require 'memprof'
GC.disable
Memprof.track { run_test_code_here }

これにより、割り当てられたオブジェクト数のリスト (クラス別と割り当てが発生したソース行の両方でグループ化されたもの) が標準出力に出力されます。

ガベージ コレクターで過度の時間が費やされるという問題がある場合、通常、割り当てトレースにより、プログラムが大量のオブジェクトを割り当てている場所が 1 つか 2 つ明らかになります。解決策がどうなるかを事前に言うことは不可能ですが、多くの場合、次のいずれかが含まれます。

  1. 計算の繰り返しを避けるための結果のキャッシュ
  2. 安全に実行できる破壊的な操作を使用する (のmap!代わりになどmap)。
  3. 反復ごとに新しいオブジェクトを割り当てるのではなく、ループ内で一時オブジェクトを再利用する (毎回その状態をリセットする)、または
  4. 何度も実行されるループ内での文字列定数 (または配列/ハッシュ リテラル) の使用を回避します (反復ごとに新しいオブジェクトが割り当てられます)。
于 2012-11-18T19:33:07.837 に答える