-6

次の 2 つのコード サンプルを検討してください。すべてのベンチマークは、サンプリングされた実行時間の平均を計算するために使用されるコンテナーの外部で行われます。Windows 7 と JDK 1.6 を実行している私のマシンでは、例 2 の平均実行時間が例 1 よりも 1,000 倍近く遅いことがわかります。他のすべての損害。誰かがこれを理解するのを手伝ってくれますか?

例 1: 配列の使用

public class TimingTest 
{

    static long startNanos, endNanos;
    static long[] samples = new long[1000];


    public static void main(String[] args) 
    {
    for (int a = 0; a < 100; a++) 
    {
        for (int numRuns = 0; numRuns < 1000; numRuns++) 
        {
            startNanos = System.nanoTime();
            long sum = 0;
            for (long i = 1; i <= 500000; i++) 
            {
                sum += i % 13;
            }
            endNanos = System.nanoTime() - startNanos;
            samples[numRuns] =(endNanos);
        }
        long avgPrim = 0L;
        for (long sample : samples) 
        {
            avgPrim += sample;
        }
        System.out.println("Avg: " + (avgPrim / samples.length) );
        }
    }
}

例 2: LinkedList の使用

public class TimingTest 
{

    static long startNanos, endNanos;
    static List<Long> samples = new LinkedList<Long>();

    public static void main(String[] args) 
    {
        for (int a = 0; a < 100; a++) 
        {
            for (int numRuns = 0; numRuns < 1000; numRuns++) 
            {
                startNanos = System.nanoTime();
                long sum = 0;
                int index = 0;
                for (long i = 1; i <= 500000; i++) 
                {
                    sum += i % 13;
                }
                endNanos = System.nanoTime() - startNanos;
                samples.add(endNanos);
            }
            long avgPrim = 0L;
            for (long sample : samples) 
            {
                avgPrim += sample;
            }
            System.out.println("Avg: " + (avgPrim / samples.size()));
        }
    }
}
4

2 に答える 2

3

ここで非常に問題があります。配列バージョンを実行すると、平均実行時間が 20000 ナノ秒になります。私の 2 GHz CPU がその時間内に 500000 回のループ反復を実行することはまったく不可能です。これは、平均ループ反復が 20000/500000 = 0.04 ns、または 0.08 cpu cpu サイクルかかることを意味するためです ...

主な理由は、タイミング ロジックのバグです。配列バージョンでは、

int index = 0;

したがって、すべてのタイミングで

samples[index++] =(endNanos);

常に最初の配列要素に割り当てられ、他の要素はすべてデフォルト値の 0 のままになります。したがって、配列の平均を取ると、すべてのサンプルの平均ではなく、最後のサンプルの 1/1000 が得られます。

実際、 index の宣言をループの外に移動しても、2 つのバリアント間に大きな違いは報告されません。

于 2013-01-14T00:51:50.727 に答える
0

a < 1コードの実際の実行は次のとおりです (わかりやすくするためにクラスの名前を変更し、時間のためにそれぞれの for ループの外側を切り取ります)。

$ for f in *.class
do
  class=$(echo $f | sed 's`\(.*\)\.class`\1`')
  echo Running $class
  java $class
done
Running OriginalArrayTimingTest
Avg: 18528
Running UpdatedArrayTimingTest
Avg: 41111273
Running LinkedListTimingTest
Avg: 41340483

明らかに、最初の懸念は@meritonが指摘したタイプミスが原因であり、質問で修正しました。テスト ケースでは、配列と LinkedList の両方がほぼ同じように動作することがわかります。一般的に言えば、LinkedList への挿入は非常に高速です。メリトンの変更で質問を更新しましたが、前者が後者よりも劇的に高速であるという主張を更新しなかったため、何を求めているのかが明確ではなくなりました。ただし、この場合、両方のデータ構造が合理的に同様に動作することがおわかりいただけたと思います。

于 2013-03-04T05:43:04.970 に答える