= CSSのDataBrowserのパフォーマンスチューニング = CSSのDataBrowserで長期間のグラフあるいは多数のグラフを描かせようとしたときに グラフを描き終わるまで非常に長時間掛かったりエラーになったりしてしまうことが良く起こる。 これはグラフを描くためのデータを格納するメモリが不足することが原因で起こるが、 メモリに関するパラメータをチューニングすることでどのようにパフォーマンスが改善されるか ベンチマークテストにより確認する。 == はじめに == CSSではJavaが使用されている。 Javaで使用するメモリにはヒープ(Javaヒープ)と非ヒープがあり、 CSSのDataBrowserでグラフを描くためのデータはヒープに格納される。 CSSの設定ファイルcss.ini内の'''{{{-vmargs}}}'''行以降でJavaで使用するメモリに関するパラメータが設定されている。 {{{ -Xmx1024m -XX:MaxPermSize=128M }}} このうち非ヒープであるPermanent領域の最大サイズを指定しているパラメータ'''{{{-XX:MaxPermSize=128M}}}''' については今回は変更しない。 ベンチマークの条件 * 使用したPCは、64bit版Windows7 Pro、Core i5(4core)、実装メモリ8GB、利用可能メモリ7.9GB、ネットワーク100Mbps * 使用したCSSはkek版3.1.2 64bit。使用したJavaは64bit Java SE 7 Update 55(1.7.0_55)。 * 使用するデータは1つ。(PFROP:BEAM:FAST_CURR 0.1秒毎の更新) * データの開始日時を固定。(2014/05/10 00:00:00) * 何日分のグラフを描くプロットファイルを多数用意しておく。(1日分、2日分、、、) * プロットファイルを開いた時からグラフを描き終わるまでの時間を測定する。 * 時間の測定にはストップウォッチを使い、1秒未満はすべて切り捨てる。 * 時間測定は最大10分とし10分を超えた場合は中断して、結果なしとする。 * 1つの測定毎にCSSを再起動する。 このような条件でメモリに関するパラメータを変化させてベンチマークを行った。 グラフの横軸は処理したデータ量[日]、縦軸は処理時間[秒]を表わす。 == ヒープサイズを増やす == Xmxパラメータはヒープの最大サイズを指定するパラメータである。 あくまでも最大サイズを指定するものであり、実際のヒープサイズはデータ量により変わり、 データ量に応じて最大サイズまで自動的に拡張される。[[BR]] 初期設定ではヒープの最大サイズが1GB(1024MB)に指定されている。 まずXmxパラメータでヒープの最大サイズを初期設定の1GB、4GB、6GB、8GBと増やした。(図1) ヒープサイズを増やせば処理可能な日数が増え、処理時間もデータ量(日数)に比例する。(Xmx近似の点線)[[BR]] ヒープサイズはデータの読み込みが進むにつれ次第に最大サイズ近くまで拡張されていった。 次にXmsパラメータをXmxと同じ値にして測定した。(図2) Xmsはヒープの初期サイズ指定で、Xmxと同じ値を指定すればヒープサイズは固定される。[[BR]] ただしヒープサイズを大きなサイズに固定したからといって、 実際にデータ量が増えなければOSがメモリを割り当てることはないのでPCのメモリを無駄に占有するわけではない。 ヒープサイズを固定した場合にXmx近似より処理時間が短く完了する比例関係部分がある。(Xms近似の点線)[[BR]] データ量がヒープのOld領域の不足が起こらないで済む場合はXms近似で処理が完了するが、 !Old領域が不足してFull GCが起こり始めるとXmx近似になっていく。 ヒープサイズを固定しない場合はヒープの拡張とともにFull GCが行われていると思われる。 [[Image(memorytuning_fig1.png, 40%)]] [[Image(memorytuning_fig2.png, 40%)]] 処理時間については、ヒープサイズを固定した場合のほうが処理時間が短縮されることが多く、 Xms近似で処理が完了する場合はXmx近似に比較して約1.38倍の高速化となる。(図3,4,5)[[BR]] 8GBの20日分の処理時間を比較すると215秒から156秒へと59秒短縮されている。 処理可能な日数については、ヒープサイズを固定した場合に改善したというよりも、 ヒープサイズが可変の場合、ヒープを拡張する際にメモリの断片化が起き、 GCを行っても断片化が完全には解消できずにメモリの利用効率が悪化しているのではないだろうか。 [[Image(memorytuning_fig3.png, 40%)]] [[Image(memorytuning_fig4.png, 40%)]] [[Image(memorytuning_fig5.png, 40%)]] == ヒープのOld領域を大きくする == ヒープのOld領域が不足してFull GCが起こると処理時間が掛かるようになることが分かったので、 Old領域を大きくするためにNewRatioパラメータを変更してみる。 NewRatioパラメータはヒープのNew領域の大きさに対するOld領域の大きさの比率を指定する。[[BR]] !NewRatio=2とした場合New1:Old2になり、New領域の大きさはヒープサイズの1/3、Old領域の大きさは2/3になる。 (似たパラメータとしてNew領域の大きさを指定する、!NewSize、MaxNewSizeというパラメータもある。) Java !HotSpot VMにはクライアントVMとサーバVMのチューニングの異なる2種類のVMがあり、 NewRatioパラメータの初期値はクライアントVMが8、サーバVMが2となっている。 PCの構成によってどちらを使用するか決定される。自分のPCでどちらのVMが使用されるかは '''{{{java -version}}}'''コマンドの出力で確認できる。[[BR]] Windowsの場合、32bit JavaではクライアントVM、64bit JavaではサーバVMが使用される。 Xms4Gとしてヒープサイズを4GBに固定して、NewRatio指定なし、!NewRatio=2、8、10、12、14、16、20と変化させた。(図6)[[BR]] !NewRatio指定なしとNewRatio=2の結果は同じであることが確認できた。(64bit Javaを使用) NewRatioを増やすにつれてXms近似の範囲で処理完了する日数が増えていくが、 次第に改善幅が小さくなっていき、16と20では同じ結果になった。 これは、NewRatioが16の場合はOld領域の大きさがヒープの94.1%(16/17)、20の場合は95.2%(20/21)と、 Old領域の大きさが1%(45MB)しか変わらないからだろう。 [[Image(memorytuning_fig6.png, 40%)]] Xms6G、Xms8Gの場合も似たような結果になった。(図7,8)[[BR]] NewRatioが16と20の場合の1%の違いは、6GBでは69MB、8GBでは91MBにすぎないが多少の改善が見られた。 4GBの場合でも1日分のデータ量の違いでは結果に差がなかったが、半日や1/4日分のデータ量の違いだとしたら 多少なりとも結果に差がでたことだろう。 [[Image(memorytuning_fig7.png, 40%)]] [[Image(memorytuning_fig8.png, 40%)]] 以上の結果から同じヒープサイズで、最大ヒープサイズを指定しただけの場合(Xmx)と、 ヒープサイズを固定かつOld領域を大きくした場合(Xms NR16)とを比較すると、 処理時間と日数(データ量)がかなり改善され、 Xmx8GとXms8G NR16の場合では同等の処理時間で10日分多いデータが表示できるようになった。(図9,10,11) さらに、少しズルい比較になるが、Xmx4GとXms8G NR16を比較すると 22日分多いデータが表示できるようになり、2.5倍に改善された。(図12) 処理時間についてはデータ量が多いためそれなりに掛かるがXms近似から外れてはいない。 [[Image(memorytuning_fig9.png, 40%)]] [[Image(memorytuning_fig10.png, 40%)]] [[Image(memorytuning_fig11.png, 40%)]] [[Image(memorytuning_fig12.png, 40%)]] == まとめ == CSSのDataBrowserで長期間のグラフあるいは多数のグラフを描かせるためには CSSに多くのヒープ(メモリ)を割り当てる必要がある。 データ量が増えるため必要なヒープも多くなるのは当然である。 しかし単にヒープの最大サイズを多くするだけでは不十分で、 ヒープサイズを固定しOld領域の割合を大きくし、 Full GCをなるべく起こさないようにチューニングすることで パフォーマンス(グラフの日数や数、処理時間)はかなり改善される。 また、PCの利用可能メモリの制限からCSSに割り当てられるヒープサイズが制限される場合でも、 Old領域の割合を大きくすることで同じヒープサイズであってもパフォーマンスを改善することができる。 == 追加情報 == 今回このベンチマークテストを行っているときに、処理時間のうちそのほとんどが ネットワーク経由でのデータ転送に掛かっていることが分かった。[[BR]] ベンチマークで使用したPCは100MbpsのHUBに繋がっていたが、 データ転送中は100Mbpsのうち98%近い帯域を使用しており、 ネットワークの速度がボトルネックになっていることが明らかだった。 そこでHUBを1Gbps(GbE)のものに交換してXms8G NR16時のベンチマークを行ってみたところ、 処理時間はほぼ半分になった。(図13) [[Image(GbE_fig13.png, 40%)]] 処理完了までの時間を次の3つに分けて詳しく測定した。 * プロットファイルを開いてからデータ転送が始まるまでの時間。(データベース側でのクエリ処理の時間と考えられる。) * データ転送に掛かる時間。 * データ転送が終了してグラフ描画が終了するまでの時間。 38日分ではFull GCが発生しているためグラフ描画時間が掛かっているが、 それを除けば3つとも日数に比例した時間が掛かっている。(図14) [[Image(GbE_fig14.png, 40%)]] 36日分の処理時間の内訳を100Mbpsと1Gbpsを比較すると、クエリ処理とグラフ描画の時間に差はなく、 データ転送にかかる時間が233秒から85秒へと148秒短縮され、約2.74倍高速化となった。(図15-1,15-2 横軸は処理時間[秒]) [[Image(GbE_fig15-1.png, 40%)]] [[Image(GbE_fig15-2.png, 40%)]] この時ネットワーク帯域のうち25%~30%を使用していた。[[BR]] このボトルネックがPC、データベース、ネットワークのどこにあるのかまでは検証していない。