2017-09-04 11 views
0

私はJavaで多くのソートアルゴリズムを実装しており、各アルゴリズムの時間と比較をしたいと考えています。現在、私は、コードの冗長性の膨大な量で、その回ごとのアルゴリズムを別々のスクリプトを持っている:6つのまたは7つの異なるソートアルゴリズムでJavaのベンチマークプログラムにメソッドを渡す

long min = 1000000; 
long startTime; 
long endTime; 

QuickSort quicksorter = new QuickSort(); 

for (int i = 0; i != 10000; ++i) { 
    startTime = System.nanoTime(); 
    quicksorter.sort(); 
    endTime = System.nanoTime(); 
    if ((endTime - startTime) < min) 
     min = endTime - startTime; 
} 

System.out.printf("Quicksort min time is %d ns.\n", min); 


BinaryInsertionSort binarysorter = new BinaryInsertionSort(); 
min = 1000000; 

for (int i = 0; i != 10000; ++i) { 
    startTime = System.nanoTime(); 
    binarysorter.sort(); 
    endTime = System.nanoTime(); 
    if ((endTime - startTime) < min) 
     min = endTime - startTime; 
} 

System.out.printf("Binary insertion sort min time is %d ns.\n", min); 

が、これは非常に非効率的な感じを開始します。

long timeit(function func) { 
    min = 1000000; 

    for (int i = 0; i != 10000; ++i) { 
     startTime = System.nanoTime(); 
     func(); 
     endTime = System.nanoTime(); 
     if ((endTime - startTime) < min) 
      min = endTime - startTime; 
    } 

    System.out.printf("Min execution time is %d ns.\n", min); 
} 

しかし、私はパラメータとしてメソッドを渡すことはお勧めできません(と不便)であることを収集します。このようなパラメータと時間彼らは明らかなように、「パイソン風」ソリューションは、方法を取るメソッドを定義することですJavaのように、一般的に行うのは不可能かもしれません。各ソータークラスはベンチマークメソッドを実装する抽象クラスから継承することができると思いますが、Javaでこれを達成するより良い方法はありますか?

+0

ちょうどJMHを使用してください:http://tutorials.jenkov.com/java-performance/jmh.html#your-first-jmh-benchmark – millimoose

答えて

2

しかし、私は、Javaのパラメータとしてメソッドを渡すことはお勧めできません(と不便)であることを収集し、一般的にそうすることはええ

不可能かもしれませんか?

Java 8以降では、引数などの汎用メソッドを渡すことができます。あなたがここで欲しいものはRunnableです。同じクラス内の二つの方法持って提供

public final class Foo 
{ 
    void f1() { /* whatever */ } 
    void f2() { /* whatever */ } 
} 

を、あなたが同様に、メソッド参照を使用して、両方のコードの時刻ができる:

final Runnable r1 = Foo::f1; 
final Runnable r2 = Foo::f2; 

及びそれらのメソッドへの参照を使用して(これ有効なラムダです):

long start, end; 

Stream.of(r1, r2).forEach(r -> { 
    start = System.nanoTime(); 
    r.run(); 
    end = System.nanoTime(); 
    System.out.println("Time spent in ns: " + (end - start)); 
}); 

その後、さらに絞り込むことができますあなたのコードは、例えばIntConsumersのように使います。


ここで、ベンチマーク目的では、1回の実行では実行できません。考慮すべきJITがあり、JITは、「一定額」の定義のために、同じコード・パスの一定量の実行後にのみ開始されます。したがって、上記のコードでは、(この表示が意味するものについて)表示が得られますが、それは絶対的なものではありません。

ベンチマークの目的では、jmhを使用することを検討してください。すべてのドキュメントをよくお読みください! JVMは同時にコードを実行する上で効率的で複雑な装置です...

1

あなたはJavaの世界で正しい行に沿って考えています。

public static long timeit(Class c) { 
    long startTime, endTime, min; 

    // new object and the method to call 
    Object instance = c.newInstance(); 
    Method method = getClass().getDeclaredMethod("sort"); 

    min = Long.MAX_VALUE; 

    for (int i = 0; i != 10000; ++i) { 
     startTime = System.nanoTime(); 
     // call the function 
     method.invoke(obj); 
     endTime = System.nanoTime(); 
     min = endTime - startTime < min ? endTime - startTime : min; 
    } 
    return min; 
} 


//then you call it like this: 
long time1 = timeit(QuickSort.class); 

はおそらくそこになるだろう、と言った:あなたはこのコンテキストで継承を台無しにしたくない場合は、1つの方法は、次のようにあなたが方法で、リフレクション経由で必要なものを達成できますいくつかのオーバーヘッドがこのアプローチに関連して導入されましたが、それでもそれはあなたに良い比較画像を与えるはずです。

+0

リフレクションはJITを妨げる可能性があるので、ベンチマークを歪ませる可能性があります。http://docs.oracle.com/javase/tutorial/reflect/index.html – Gene

関連する問題