1

クライアント コードのいくつかのメソッドのベンチマークを行って、それらのメソッドにかかる時間を確認しています。したがって、複数のスレッドを生成するマルチスレッド プログラムを作成し、それらのメソッドがクライアント コードとサーバー側コードでどれだけの時間を費やしているかを測定します。

私は次のようにConcurrentHashMap宣言しています

public static ConcurrentHashMap<Long, Long> map = new ConcurrentHashMap<Long, Long>();

今、私は X ミリ秒で戻ってきた呼び出しの数を調べようとしているので、それらの数値を上記のマップに保存しています。したがって、上記のマップは次のようなものを保存します-

KEY will be Milliseconds
and VALUE will be Number of calls came back in those milliseconds.

以下はコードです、私は持っています。

final long start = System.nanoTime();

method.getInformation();

final long end = System.nanoTime() - start;
final long key = end / 1000000L;
boolean done = false;
while(!done) {
    Long oldValue = map.putIfAbsent(key, 1L);
    if(oldValue != null) {
        done = map.replace(key, oldValue, oldValue + 1);
    } else {
        done = true;
    }
}

上記のコードに問題があるかどうかを確認しようとしていますか?

私が尋ねている理由は、私が実行している場合Multithreading programserver CPU usage通常は周りに行くから80-90%です。しかし、サーバー側のコードから上記のベンチマーク コードを削除するとCPU usage80-90%. それが理由です。上記の同じシナリオを満たすことができる上記のベンチマークコードを書くためのより良い方法があるかどうかを確認しようとしていますか?

助けてくれてありがとう。

更新しました:-

UNIXでTOPコマンドを使用して、サーバー側でCPUとMEMORYの使用状況を監視していました-

top - 17:13:18 up 25 days, 23:24,  4 users,  load average: 1.72, 1.43, 1.04
Tasks: 114 total,   1 running, 111 sleeping,   0 stopped,   2 zombie
Cpu0  : 79.2%us,  5.8%sy,  0.0%ni, 23.1%id,  0.0%wa,  0.0%hi,  1.9%si,  0.0%st
Cpu1  : 83.7%us,  3.7%sy,  0.0%ni, 40.7%id,  0.0%wa,  0.0%hi,  1.9%si,  0.0%st
Mem:   6127684k total,  5122736k used,  1004948k free,   240436k buffers
Swap:  1331196k total,        0k used,  1331196k free,  2485984k cached

以下は、実行中のスナップショットです。キャプチャしたばかりです

4

3 に答える 3

0

そこで、あなたのタイム チェック コードを使って簡単なテストを行ったところ、クアッド コアの 2013 Macbook Pro で 8.8 秒で100 万回実行することができました。これは、各呼び出しのコストが 8ns 未満であることを意味します (私のタイミングは壁時計であり、スレッドのものを考慮しているため)。これはかなり安いIMOです。100 個のスレッドで 0 から 1000000 までのランダムな値を貼り付けていたところ、20 ~ 30 MB 未満のコアを使用するように見える 631k エントリのヒープ サイズになりました。

あなたの通話時間コードは大きなパフォーマンスの問題ではないようです。各スレッドが大量のメモリにアクセスしていて、コードが実行しているのはメモリ バリアにぶつかっているだけなのだろうか。コードをフィールドの単一の更新volatileまたは何かに置き換えて、同じ動作が得られるかどうかを確認するバリアを強制するのは興味深いかもしれません。


あなたのコードに問題があるとはすぐには思いませんし、パフォーマンスに大きな問題があるとは思いません。

しかし、そのマップがどれだけ大きくなっているのか気になります。マップ内に多数のエントリがある状態で長時間実行している場合、メモリ要件が非常に大きくなるようです。-Xmx引数を使用してメモリを増やしてみてください。

メモリの場合、CPU の問題は GC に関連している可能性があります。Jconsole を使用して、メモリが不足しているかどうかを確認します。

于 2013-04-28T00:11:28.070 に答える
0

パフォーマンス/リソース使用の問題:

  • 各呼び出し中の HashMap の読み取りと書き込みはコストがかかる可能性があり、同時ハッシュマップはさらにコストがかかります。必須ではありません。
  • また、System.nanoTime() を呼び出しますが、これはコストがかかる可能性があり、反復ごとにこれを行います。必須ではありません。

私のおすすめ

  • メソッドが実行された回数で静的実行カウ​​ンターを宣言する
  • 同期ブロックで、カウンターをインクリメントします
  • カウンターがしきい値 (例: 1000) に達すると、経過時間をミリ秒単位で決定します
  • 経過時間をリストに記録する

    static List<long> methodElapsedMillisList = new ArrayList<long>();
    final int methodCountBlock = 1000; 
    static long methodCountStartMillis = System.currentTimeMillis();
    static int methodCount = 0;
    static Object methodCountMonitorObj = new Object();
    
    
    // within instrumented method:
    synchronised (methodCountMonitorObj) {
           methodCount++;
           if (methodCount > methodCountBlock ) {
                long newMethodCountStartMillis = System.currentTimeMillis();
                long elapsedMillis = newMethodCountStartMillis - methodCountStartMillis;
                methodCountStartMillis = newMethodCounterStartMillis;
                methodElapsedMillisList.add(elapsedMillis);
                methodCount = 0;
           }
    }
    
于 2013-05-01T08:18:09.257 に答える
0

ここには、潜在的なパフォーマンスの問題がいくつかあります。

  1. ベンチマーク コードはSystem.nanoTime()、各リクエストに 2 つの呼び出しを追加しています。要求に実際の作業がどれだけ含まれているかによっては、これらの呼び出しが重要になる可能性があります。

  2. を使用して同時実行性のボトルネックを削減しようとしましたがConcurrentHashMap、完全には解消されません。実際、同じミリ秒数のリクエストが多数ある場合、その特定のカウンターにボトルネックが発生します。特定のカウンターで競合が発生すると、異なるスレッドが競合して更新するため、「スピン」が発生します。

  3. (仮説として) マップが非常に大きくなると、メモリ使用量に関連する問題が発生し始める可能性があります。たとえば、ワーキング セットの増加、キャッシュと TLB の競合の増加、スラッシングなどです。

しかし、肝心なのは、パフォーマンス測定コードを追加すると、システムのパフォーマンス特性が変わる可能性があるということです。

于 2013-04-28T01:46:30.007 に答える