負荷テストの分析グラフ
JMeter VS プログラマー自作ツールで書いたのだが、JMterではどうしてもできない負荷テスト(HTTPリクエストと同等の内容をDB渡し)があり、JMeterの前処理を書いて、CSVをJMeterに渡そうかなと思ったのだがやめた。複雑すぎる。なので、自作の負荷テストツールを改造して使用することにした。
自作テストツールがJMeterと違うところは、指定時間でスレッドが階乗的に増えて行き、指定数まで増えたら、スレッドが一回ごとに終了しないでそのまま、リクエスト送信、レスポンス受信を繰り返すことだ。実際のイントラシステムでWEB渡ししてるところは、こんな感じの処理のほうが多いのではなかろうか?自作テストツールのソースは今度、機会があるときに載せます。このくらいであれば、誰でも作れそうな気はするが・・・
で・・・一番大きな問題は、自作負荷テストツールでテストするのは良いとして・・・最新のJMeterが出すような分析グラフが無い。膨大なログをエビデンスでつけたとして、「何これ?」と言われそう。困った。そんな時、岡崎さんという方のスループットを計測、分析しよう(3) 〜JMeterから取得したデータの分析〜を見た。これは、ちょっと昔、JMeterにグラフ表示が無かったときに、エクセルでスループットの分析グラフを出す方法。そうだ!自作ツールも通信ログはこのカタチで出せば、この方法で分析グラフができるではないか!おお!岡崎さん!ありがとう。感謝。謝謝!
当方テスト環境にACTIVE-PERLを入れ込むことは無理なので、岡崎さんの書いたPERLのプログラムをC#(visualStudio-Express edition)で書き直してみた。しかし、やってみると、テキスト(CSV)とか仮想配列を使用した時のPerlのすごさをあらためて知らされた次第。以下、C#に移植したPG。
calcfd hogehoge.csv > outfile.csv として使用する。出力CSVの分析グラフはスループットを計測、分析しよう(3) 〜JMeterから取得したデータの分析〜を請参にしてください。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Calcfd { class Program { const int timegrid = 1000; private static int start_time, elapsed_time, return_code, grid_begin, grid_end; private static string url; static void Main(string[] args) { try{ System.IO.StreamReader streamReader = new System.IO.StreamReader(args[0], System.Text.Encoding.GetEncoding("Shift_JIS")); Dictionary<string, int> concurrency = new Dictionary<string, int>(); Dictionary<string, int> throughput = new Dictionary<string, int>(); while (streamReader.Peek() != -1) { string[] stringBuffer; stringBuffer = streamReader.ReadLine().Split(','); start_time = int.Parse(stringBuffer[0].ToString()); elapsed_time = int.Parse(stringBuffer[1].ToString()); url = stringBuffer[2].ToString(); return_code = int.Parse(stringBuffer[3].ToString()); grid_begin = (int)(start_time / timegrid); grid_end = (int)((start_time + elapsed_time) / timegrid); for (int g = grid_begin; g <= grid_end; g++) { if( !concurrency.ContainsKey(g.ToString()) ){ concurrency[g.ToString()] = 1; } else{ concurrency[g.ToString()]++; } } if( !throughput.ContainsKey(grid_end.ToString())){ throughput[grid_end.ToString()] = 1; } else{ throughput[grid_end.ToString()]++; } } streamReader.Close(); Console.Write( "time(ms),concurrency(time grid=" + timegrid + "ms),throughput(tps)\n"); SortedDictionary<string, int> sconcurrency = new SortedDictionary<string, int>(concurrency); foreach (KeyValuePair<string, int> kvp in sconcurrency) { if( !throughput.ContainsKey(kvp.Key) ){ throughput[kvp.Key] = 0; } Console.WriteLine(@"{0},{1},{2}", int.Parse(kvp.Key) * timegrid, kvp.Value, throughput[kvp.Key]); } } catch (Exception e){ Console.WriteLine("{0} Exception caught.", e); } } } }
以上です。