IntelJavaパフォーマンスアーキテクトのEricKaczmarek(元々はここで公開)からのこのゲスト投稿では、100%YCSB読み取りに焦点を当ててApache HBaseのJavaガベージコレクション(GC)を調整する方法について説明しています。
Apache HBaseは、NoSQLデータストレージを提供するApacheオープンソースプロジェクトです。多くの場合、HDFSと一緒に使用され、HBaseは世界中で広く使用されています。有名なユーザーには、Facebook、Twitter、Yahooなどがあります。開発者の観点から見ると、HBaseは、「構造化データ用の分散ストレージシステムであるGoogleのBigtableをモデルにした、分散型のバージョン管理された非リレーショナルデータベース」です。 HBaseは、スケールアップ(つまり、より大きなサーバーへの展開)またはスケールアウト(つまり、より多くのサーバーへの展開)のいずれかによって、非常に高いスループットを簡単に処理できます。
ユーザーの観点からは、各クエリのレイテンシーは非常に重要です。ユーザーと協力してHBaseワークロードをテスト、調整、最適化すると、99パーセンタイルの運用レイテンシーを本当に望んでいるかなりの数に遭遇します。これは、クライアントの要求からクライアントへの応答まで、すべて100ミリ秒以内のラウンドトリップを意味します。
いくつかの要因が遅延の変動に寄与します。最も破壊的で予測不可能なレイテンシ侵入者の1つは、Java仮想マシン(JVM)の「世界を止める」ガベージコレクション(メモリクリーンアップ)の一時停止です。
これに対処するために、Oraclejdk7u21およびjdk7u60G1(Garbage 1st)コレクターを使用していくつかの実験を試みました。使用したサーバーシステムは、ハイパースレッディングを備えたIntel Xeon Ivy-bridge EPプロセッサ(40個の論理プロセッサ)に基づいていました。 256GB DDR3-1600 RAMと、ローカルストレージとして3つの400GBSSDを搭載していました。この小さなセットアップには、負荷が適切にスケーリングされた単一のノードで構成された1つのマスターと1つのスレーブが含まれていました。 HFileストレージにはHBaseバージョン0.98.1とローカルファイルシステムを使用しました。 HBaseテストテーブルは4億行として構成され、サイズは580GBでした。デフォルトのHBaseヒープ戦略を使用しました。ブロックキャッシュに40%、memstoreに40%です。 YCSBは、HBaseサーバーにリクエストを送信する600のワークスレッドを駆動するために使用されました。
次のグラフは、-XX:+UseG1GC -Xms100g -Xmx100g -XX:MaxGCPauseMillis=100
を使用して1時間100%読み取りを実行しているjdk7u21を示しています。 。使用するガベージコレクター、ヒープサイズ、および目的のガベージコレクション(GC)の「世界を止める」一時停止時間を指定しました。
図1:GC一時停止時間の激しい変動
この場合、GCの一時停止が激しく揺れています。 GCの一時停止の範囲は、最初のスパイクが17.5秒に達した後、7ミリ秒から5秒でした。
次のグラフは、定常状態での詳細を示しています。
図2:定常状態中のGC一時停止の詳細
図2は、GCの一時停止が実際には3つの異なるグループに分類されることを示しています。(1)1〜1.5秒。 (2)0.007秒から0.5秒の間。 (3)1.5秒から5秒の間にスパイクします。これは非常に奇妙だったので、最近リリースされたjdk7u60をテストして、データが異なるかどうかを確認しました。
まったく同じJVMパラメーターを使用して同じ100%読み取りテストを実行しました:-XX:+UseG1GC -Xms100g -Xmx100g -XX:MaxGCPauseMillis=100
。
図3:一時停止時間の急上昇の処理が大幅に改善されました
Jdk7u60は、落ち着く段階での最初のスパイク後の一時停止時間のスパイクを処理するG1の機能を大幅に改善しました。 Jdk7u60は、1時間の実行中に1029の若いGCと混合GCを作成しました。 GCは約3.5秒ごとに発生しました。 Jdk7u21は286個のGCを作成し、各GCは約12.6秒ごとに発生しました。 Jdk7u60は、大きなスパイクなしで0.302〜1秒の一時停止時間を管理できました。
下の図4は、定常状態での150のGC一時停止を詳しく示しています。
図4:良いが、十分ではない
定常状態の間、jdk7u60は平均休止時間を約369ミリ秒に保つことができました。 jdk7u21よりもはるかに優れていましたが、それでも–Xx:MaxGCPauseMillis=100
で指定された100ミリ秒の要件を満たしていませんでした。 。
1億秒の一時停止時間を取得するために他に何ができるかを判断するには、JVMのメモリ管理とG1(ガベージファースト)ガベージコレクターの動作についてさらに理解する必要がありました。次の図は、G1がYoungGenコレクションでどのように機能するかを示しています。
図5:CharlieHuntとMonicaBeckwithによる2012JavaOneプレゼンテーションのスライド:「G1ガベージコレクターのパフォーマンスチューニング」
JVMが起動すると、JVM起動パラメータに基づいて、JVMのヒープをホストするために大きな連続メモリチャンクを割り当てるようにオペレーティングシステムに要求します。そのメモリチャンクは、JVMによってリージョンに分割されます。
図6:CharlieHuntとMonicaBeckwithによる2012JavaOneプレゼンテーションのスライド:「G1ガベージコレクターのパフォーマンスチューニング」
図6に示すように、JavaプログラムがJava APIを使用して割り当てるすべてのオブジェクトは、最初に左側の若い世代のEdenスペースに到達します。しばらくすると、エデンがいっぱいになり、若い世代のGCがトリガーされます。まだ参照されている(つまり「生きている」)オブジェクトは、サバイバースペースにコピーされます。オブジェクトが若い世代のいくつかのGCを生き残ると、それらは古い世代のスペースに昇格します。
Young GCが発生すると、ライブオブジェクトを安全にマークしてコピーするために、Javaアプリケーションのスレッドが停止します。これらの停止は、悪名高い「世界を停止する」GC一時停止であり、一時停止が終了するまでアプリケーションが応答しなくなります。
図7:CharlieHuntとMonicaBeckwithによる2012JavaOneプレゼンテーションのスライド:「G1ガベージコレクターのパフォーマンスチューニング」
旧世代も混雑する可能性があります。特定のレベルで--XX:InitiatingHeapOccupancyPercent=?
によって制御されます デフォルトは合計ヒープの45%で、混合GCがトリガーされます。若い世代と古い世代の両方を収集します。混合GCの一時停止は、混合GCが発生したときにYounggenがクリーンアップするのにかかる時間によって制御されます。
したがって、G1で見ることができるように、「世界を止める」GCの一時停止は、G1がライブオブジェクトをマークしてエデン空間からコピーする速度によって支配されます。これを念頭に置いて、HBaseメモリ割り当てパターンがG1 GCを調整して、100ミリ秒の望ましい一時停止を取得するのにどのように役立つかを分析します。
HBaseには、ヒープの大部分を消費する2つのメモリ内構造があります。BlockCache
、読み取り操作のためにHBaseファイルブロックをキャッシュし、Memstoreが最新の更新をキャッシュします。
図8:HBaseでは、2つのメモリ内構造がヒープの大部分を消費します。
HBaseのBlockCache
のデフォルトの実装 LruBlockCache
です 、これは単に大きなバイト配列を使用してすべてのHBaseブロックをホストします。ブロックが「削除」されると、そのブロックのJavaオブジェクトへの参照が削除され、GCがメモリを再配置できるようになります。
LruBlockCache
を形成する新しいオブジェクト およびMemstore
最初に若い世代のエデンスペースに行きます。彼らが十分に長生きする場合(つまり、LruBlockCache
から追い出されない場合 またはMemstoreからフラッシュされます)、その後、数世代の若い世代のGCの後、古い世代のJavaヒープに移行します。旧世代の空き容量が特定のthreshOld
未満の場合 (InitiatingHeapOccupancyPercent
まず、混合GCは、旧世代のいくつかのデッドオブジェクトを開始してクリアし、若い世代からライブオブジェクトをコピーし、若い世代のEdenと古い世代のHeapOccupancyPercent
を再計算します。 。最終的に、HeapOccupancyPercent
一定のレベルに達する、FULL GC
これにより、GCは一時停止して、旧世代内のすべての死んだオブジェクトをクリーンアップします。
「-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy
によって生成されたGCログを調べた後 「、HeapOccupancyPercent
に気づきました HBase 100%読み取り中に完全なGCを誘発するほど大きくなることはありません。私たちが見たGCの一時停止は、Younggenの「stoptheworld」の一時停止と、時間の経過とともに増加する参照処理によって支配されていました。
その分析が完了したら、デフォルトのG1GC設定に3つのグループの変更を加えました。
-
-XX:+ParallelRefProcEnabled
を使用します このフラグがオンになっている場合、GCは複数のスレッドを使用して、Youngおよび混合GC中に増加する参照を処理します。 HBaseのこのフラグを使用すると、GCリマーキング時間が75%短縮され、全体的なGC一時停止時間が30%短縮されます。 -
Set -XX:-ResizePLAB and -XX:ParallelGCThreads=8+(logical processors-8)(5/8)
プロモーションローカル割り当てバッファー(PLAB)は、Youngコレクション中に使用されます。複数のスレッドが使用されます。各スレッドは、SurvivorまたはOldスペースのいずれかにコピーされるオブジェクトにスペースを割り当てる必要がある場合があります。 PLABは、空きメモリを管理する共有データ構造をめぐるスレッドの競合を回避するために必要です。各GCスレッドには、サバイバルスペース用に1つ、オールドスペース用に1つのPLABがあります。 GCスレッド間の大きな通信コストと各GC間の変動を回避するために、PLABのサイズ変更を停止したいと思います。GCスレッドの数を8+(論理プロセッサ-8)(で計算されたサイズに固定したいと思います。 5/8)。この式は最近Oracleによって推奨されました。両方の設定を使用すると、実行中のGCの一時停止をよりスムーズに行うことができます。 -
-XX:G1NewSizePercent
を変更します 100GBヒープのデフォルトは5から1-XX:+PrintGCDetails and -XX:+PrintAdaptiveSizePolicy
からの出力に基づく 、G1が目的の100GC一時停止時間を満たせなかった理由は、エデンの処理にかかった時間であることに気づきました。つまり、テスト中にG1が5GBのエデンを空にするのに平均369ミリ秒かかりました。次に、-XX:G1NewSizePercent=
を使用してエデンのサイズを変更しました フラグを5から1に下げます。この変更により、GCの一時停止時間が100ミリ秒に短縮されました。
この実験から、EdenをクリーンアップするG1の速度は100ミリ秒あたり約1 GB、または使用したHBaseセットアップでは1秒あたり10GBであることがわかりました。
その速度に基づいて、-XX:G1NewSizePercent=
を設定できます。 したがって、エデンのサイズは約1GBに保つことができます。例:
- 32GBヒープ、
-XX:G1NewSizePercent=3
- 64GBヒープ、–
XX:G1NewSizePercent=2
- 100GB以上のヒープ、
-XX:G1NewSizePercent=1
- したがって、HRegionserverの最終的なコマンドラインオプションは次のとおりです。
-
-XX:+UseG1GC
-
-Xms100g -Xmx100g
(テストで使用したヒープサイズ) -
-XX:MaxGCPauseMillis=100
(テストで必要なGC一時停止時間) - –
XX:+ParallelRefProcEnabled
-
-XX:-ResizePLAB
-
-XX:ParallelGCThreads= 8+(40-8)(5/8)=28
-
-XX:G1NewSizePercent=1
-
100%読み取り操作を1時間実行した場合のGC一時停止タイムチャートは次のとおりです。
図9:最も高い初期沈降スパイクが半分以上減少しました。
このチャートでは、最も高い初期セトリングスパイクでさえ3.792秒から1.684秒に短縮されました。最も初期のスパイクは1秒未満でした。決済後、GCは一時停止時間を約100ミリ秒に保つことができました。
次のグラフは、定常状態でのチューニングありとチューニングなしのjdk7u60の実行を比較しています。
図10:jdk7u60は、定常状態でチューニングありとなしで動作します。
上記で説明した単純なGCチューニングにより、平均106ミリ秒と7ミリ秒の標準偏差で、約100ミリ秒の理想的なGC一時停止時間が得られます。
概要
HBaseは応答時間が重要なアプリケーションであり、GCの一時停止時間を予測および管理可能にする必要があります。 Oracle jdk7u60では、-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy
によって報告されたGC情報に基づきます 、GCの一時停止時間を希望の100ミリ秒に調整できます。
Eric Kaczmarekは、IntelのソフトウェアソリューショングループのJavaパフォーマンスアーキテクトです。彼は、Intelプラットフォーム向けのビッグデータフレームワーク(Hadoop、HBase、Spark、Cassandra)を有効にして最適化するためのIntelの取り組みを主導しています。
パフォーマンステストで使用されるソフトウェアとワークロードは、Intelマイクロプロセッサでのみパフォーマンスが最適化されている可能性があります。 SYSmarkやMobileMarkなどのパフォーマンステストは、特定のコンピューターシステム、コンポーネント、ソフトウェア、操作、および機能を使用して測定されます。これらの要因のいずれかを変更すると、結果が変わる可能性があります。他の製品と組み合わせた場合のその製品のパフォーマンスを含め、予定されている購入を完全に評価するのに役立つ他の情報とパフォーマンステストを参照する必要があります。
Intelプロセッサの数は、パフォーマンスの指標ではありません。プロセッサ番号は、各プロセッサファミリ内の機能を区別します。異なるプロセッサファミリ間ではありません。 http://www.intel.com/products/processor_numberにアクセスします。
Copyright 2014 Intel Corp. Intel、Intelロゴ、およびXeonは、米国およびその他の国におけるIntelCorporationの商標です。