パフォーマンステストツールのCoordinated Omissionの問題



作者:唐劉
以前からGil大神の「Your Load Generator Is Probably Lying To You-Take The Red Pill And Find Out Why」を見たことがありますが、性能テストツールcoordinated omissionの問題について言及していましたが、当時はあまり気にしていませんでした.ここ数日、独自のパフォーマンステストツールgo-ycsb(https://github.com/pingcap/go-ycsb/issues/26)という質問をして、私は急に発見しました.私たちもいたのです.
coordinated omissionとは
まずcoordinated omissionとは何かを言います.ほとんどのbenchmarkツールでは、通常、複数のスレッドを起動し、各スレッドがrequestを順次送信し、responseを受け入れ、次の送信を継続するモデルです.私たちが記録したlatencyは通常response time-request timeです.これはmake senseに見えますが、実際には問題があります.
簡単な例では、私たちがKFCに行ってチキンを買って、それから私たちは1つの列の後ろに並んで、前に3人がいて、2人が早くて、30秒で完成して、それから3番目の墨跡は半日で、5分かかって、それから私に着いて、30秒で完成しました.私にとって、私は絶対に私のlatencyが30秒だとは思いません.列に並ぶ時間2 x 30+300を計算し、サービス時間30秒を加えるので、私の総時間は390秒かかります.ここでは違いを見たかどうか分かりませんが、市販されている多くの性能テストツールは、サービス時間を実用的に使用していますが、待機時間は含まれていません.
もう1つの例では、パフォーマンステストツールが10 ops/secの頻繁な要求を送信する必要があると仮定します.すなわち、100 msごとに1つ送信することを望んでいます.前の9つのリクエストは,それぞれ50 usで返されたが,10番目のリクエストは1 s続き,後ろのリクエストは50 usであった.明らかに,1 sではシステムにカートンが現れたが,このときは実は1つのリクエストしか送られず,システムをよくテストしていない.
YCSB
最初のキューの例では、latencyをよりよく計算するために、YCSBはintended timeの概念を導入し、すなわち、実際のキュー時間を記録する.これは、throttleのときに記録されるlocal thread変数を使用します.
private void throttleNanos(long startTimeNanos) {
 //throttle the operations
 if (_targetOpsPerMs > 0)
    {
 // delay until next tick
 long deadline = startTimeNanos + _opsdone*_targetOpsTickNs;
        sleepUntil(deadline);
        _measurements.setIntendedStartTimeNs(deadline);
    }
}

次に、intended timeを使用してキュー時間を計算します.
public Status read(String table, String key, Set fields,
                 Map result) {
 try (final TraceScope span = tracer.newScope(scopeStringRead)) {
 long ist = measurements.getIntendedtartTimeNs();
 long st = System.nanoTime();
        Status res = db.read(table, key, fields, result);
 long en = System.nanoTime();
        measure("READ", res, ist, st, en);
        measurements.reportStatus("READ", res);
 return res;
    }
}

YCSBがtargetを開いている場合にのみintended timeが機能することに注意してください.
私は当初YCSBコードを見ていたとき、なぜ2つの時間があるのか分からなかったし、intended timeが何なのか分からなかったので、coordinated omissionを振り返ってやっと分かった.つまりYCSBはintended timeによりキュー時間を計算する.
しかし、YCSBは上記の2つ目の問題を解決していません.もしシステムが本当にカードマスターが現れたら、テストクライアントはカードマスターについています.同期送信要求だからです.ネットで検索してみると、Paperの「Coordinated Omission in NoSQL Database Benchmarking」を見て、同期を非同期に変更する方法について言及しました.つまり、毎回のタスクはFutureで、まずtargetに基づいてFutureを周波数で送ればいいので、このFutureがいつ完成するか、後で話します.しかも非同期なので、カードマスターの後ろからのリクエストはありません.
Go YCSB
では、go-ycsbについて、私たちはどのようにこの問題を解決しますか?私が今唯一考えているのは、Goのgoroutineを利用して、一定の周波数でgoroutineを生成し、テストを実行することです.もちろんGo自身にもスケジューリングのオーバーヘッドがありますが、ここでも排除する必要があります.テストするサービスにカートンが現れた場合、大量のgoroutineが解放されず、最終的にOOMになります.この様子は残虐に見えるが、これこそ予想に合っている.
これはただの考えで、具体的にはまだしていません.一つの原因は他の言語とは異なり、Goのgoroutineは実は生まれつきたくさん咲くので、通常私は何千もの同時テストをしています.もし私たちが1000個の同時テストを持っているとしたら、1 msに1回の頻度で、実はgoroutineごとに順次送信したのと同じです.もちろん、ないよりはましです.もし興味があれば、PRを提出してください.あるいは、メールで詳しく議論してください[email protected].
原文:性能テストツールのCoordinated Omission問題