0

リモート サーバーに多くの呼び出しを発行するストレス テストを作成しています。テスト後に次の統計を収集したいと考えています。

  1. リモート呼び出しの待ち時間 (ミリ秒単位)。
  2. リモート サーバーが処理できる 1 秒あたりの操作数。

(2) はうまく取得できますが、(1) に問題があります。私の現在の実装は、この他のSOの質問に示されているものと非常に似ています。そして、その質問で説明されているのと同じ問題がSystem.currentTimeMillis()あります。複数のスレッドでテストを実行すると、 using によって報告されるレイテンシが予想よりも長くなります。

私は問題を分析しましたが、問題はスレッドのインターリーブに起因していると確信しています (詳細については、上記でリンクした他の質問への回答を参照してください) System.currentTimeMillis()。これは、この問題を解決する方法ではありません。

を使用してそれを実行できるはずですjava.lang.management。これには、次のようないくつかの興味深い方法があります。

  1. ThreadMXBean.getCurrentThreadCpuTime()
  2. ThreadMXBean.getCurrentThreadUserTime()
  3. ThreadInfo.getWaitedTime()
  4. ThreadInfo.getBlockedTime()

私の問題は、API を読んだにもかかわらず、これらのメソッドのどれが私が望むものを提供してくれるのかまだはっきりしていないことです。私がリンクした他のSOの質問のコンテキストでは、これが必要なものです:

long start_time = **rightMethodToCall()**;

result = restTemplate.getForObject("Some URL",String.class);
long difference = (**rightMethodToCall()** - start_time);

そのためdifference、マルチスレッド環境であっても、リモート呼び出しにかかった時間の非常に適切な概算が得られます。

制限: コードのブロックをブロックで保護することは避けたいと思いますsynchronized。私のプログラムには、実行を継続できるようにしたい他のスレッドがあるからです。

編集: 詳細情報を提供します。:

問題は次のとおりです。リモート呼び出しの時間を計りたいのですが、リモート呼び出しだけです。System.currentTimeMillisorを使用しSystem.nanoTime()、コアよりも多くのスレッドがある場合、このスレッドをインターリーブすることができます。

  1. スレッド 1: 長い start_time ...
  2. スレッド 1: 結果 = ...
  3. スレッド 2: 長い start_time ...
  4. スレッド 2: 結果 = ...
  5. スレッド 2: 長い違い ...
  6. スレッド 1: 長い違い ...

その場合、Thread2 によって計算された差は正しいのですが、Thread1 によって計算された差は正しくありません (必要以上に大きくなります)。つまり、Thread1 の差の測定では、4 行目と 5 行目の時間を除外したいのですが、この時間はスレッドが待機していたのでしょうか。

他の人がそれをよりよく理解するのに役立つ場合に備えて、別の方法で質問を要約します (この引用は、@ jason-c が彼のコメントでどのように述べているかです):

[私は] リモート呼び出しの時間を計ろうとしていますが、テストの量を増やすためだけに複数のスレッドでテストを実行しています。

4

1 に答える 1

1

使用しますSystem.nanoTime()(ただし、この回答の最後にある更新を参照してください)。

ユーザーが認識する待ち時間はスレッドの CPU 時間ではなく実時間であるため、現在のスレッドの CPU またはユーザー時間を使用したくないことは間違いありません。また、現在のスレッドのブロックまたは待機時間も使用したくありません。これは、測定しようとしているものを正確に表していないスレッドごとの競合時間を測定するためです。

System.nanoTime()高解像度から比較的正確な結果を返します (粒度は、技術的には と同等またはそれ以上であることが保証されていますがcurrentTimeMillis()、実際にははるかに優れている傾向があり、通常QueryPerformanceCounterは Windows やLinux などのハードウェア クロックまたはその他のパフォーマンス タイマーで実装されます)。clock_gettime基準点が固定された時計であり、測定しようとしているものを正確に測定します。

long start_time = System.nanoTime();
result = restTemplate.getForObject("Some URL",String.class);
long difference = (System.nanoTime() - start_time);
long milliseconds = difference / 1000000;

System.nanoTime()独自の問題がありますが、パラノイアに巻き込まれないように注意してください。ほとんどのアプリケーションでは、これで十分です。たとえば、オーディオ サンプルをハードウェアなどに送信する際の正確なタイミングのために使用したくない場合があります (Java で直接行うことはありません)。

更新 1:

さらに重要なことは、測定値が予想よりも長いことをどのようにして知ることができるでしょうか? 測定値が実際の壁時計時間を示していて、一部のスレッドが他のスレッドよりも時間がかかっている場合でも、一部のユーザーより長い遅延時間を経験するため、それはユーザーが認識するレイテンシーを正確に表しています。

更新 2 (コメントの説明に基づく):

上記の私の答えの多くは、その時点でもまだ有効です。しかし、さまざまな理由で。

スレッドごとの時間を使用しても、リモート リクエストの処理中にスレッドがアイドル状態または非アクティブになる可能性があるため、正確な表現が得られません。したがって、認識されたレイテンシの一部であっても、その時間を測定から除外することになります。

リモート サーバーが、あなたが行っている同時リクエストの処理に時間がかかることによって、さらなる不正確さがもたらされます。これは、追加する追加の変数です (ただし、リモート サーバーがビジーであることを表すものとしては許容できる場合があります)。

経過時間も完全に正確ではありません。これまで見てきたように、ローカル スレッドのオーバーヘッドの変動によって、単一要求のクライアント アプリケーションには通常存在しない余分な待ち時間が追加される可能性があるためです (ただし、これは、単一要求のクライアント アプリケーションの代表としては許容できる場合があります)。マルチスレッドですが、これは制御できない変数です)。

これら 2 つのうち、ウォール タイムは、スレッドごとの時間よりも実際の結果に近づくため、前の回答を上に残しました。いくつかのオプションがあります:

  • 単一のスレッドで連続してテストを実行できます。これは、最終的には、指定された要件を達成するための最も正確な方法です
  • コアよりも多くのスレッドを作成することはできませんでした。たとえば、各コアにバインドされたアフィニティ (トリッキー: Java スレッド アフィニティ) を持つ固定サイズのスレッド プールと、それぞれのタスクとして実行される測定値です。もちろん、これにより、制御できない基本メカニズムの同期により、変数が追加されます。これにより、インターリーブのリスク軽減される可能性があります (特にアフィニティーを設定した場合) が、JVM が実行している他のスレッドやシステム上の他の無関係なプロセスなどを完全に制御することはできません。
  • リモート サーバーでの要求処理時間を測定できます。もちろん、これはネットワーク遅延を考慮していません。
  • 現在のアプローチを引き続き使用し、結果に対して統計分析を行って外れ値を取り除くことができます。
  • これをまったく測定することはできませんでした。単純にユーザー テストを実行し、コメントを待ってから最適化を試みます (つまり、とにかく開発している人々で測定します)。これを最適化する唯一の理由が UX のためである場合、ユーザーが快適なエクスペリエンスを提供し、待ち時間が完全に許容できる場合に適している可能性があります。

また、これはシステム上の他の無関係なスレッドがタイミングに影響を与えないことを保証するものではありませんが、そのため、a) テストを複数回実行して (明らかに) 平均し、b) 許容可能なあなたがOKであるタイミングエラーの要件(たとえば、0.1ミリ秒の精度までこれを本当に知る必要がありますか?)。

個人的には、最初のシングル スレッド アプローチを実行して一晩または週末に実行させるか、既存のアプローチを使用して結果から外れ値を取り除き、タイミングの誤差を許容します。目標は、十分な誤差範囲内で現実的な見積もりを見つけることです。また、許容できるものを決定する際に、この情報を最終的にどうするかを検討する必要があります。

于 2013-11-05T22:53:16.747 に答える