2

他のスレッド(https://stackoverflow.com/a/397617/1408611を参照)で行われたベンチマークにより、Java6のinstanceofは実際には非常に高速であることが示されました。これはどのように達成されますか?

単一継承の場合、最速のアイデアは、各クラスが[low、high]間隔を維持し、instanceofが単純な間隔包含テスト、つまり2つの整数比較であるネストされた間隔エンコーディングを使用することです。しかし、それはどのようにインターフェース用に作られていますか(間隔の包含は単一の継承に対してのみ機能するため)?そして、クラスの読み込みはどのように処理されますか?新しいサブクラスをロードするということは、多くの間隔を調整する必要があることを意味します。

4

1 に答える 1

5

私の知る限り、各クラスは、それが拡張するすべてのクラスとそれが実装するインターフェースを知っています。これらは、O(1) ルックアップ時間を提供するハッシュ セットに格納できます。

コードが頻繁に同じ分岐を取る場合、分岐を取るべきかどうかを判断する前に CPU が分岐内のコードを実行できるため、ほとんどコストを削減できます。

マイクロ ベンチマークは 4 年前に実行されたので、最新の CPU と JVM ははるかに高速であると期待しています。

public static void main(String... args) {
    Object[] doubles = new Object[100000];
    Arrays.fill(doubles, 0.0);
    doubles[100] = null;
    doubles[1000] = null;
    for (int i = 0; i < 6; i++) {
        testSameClass(doubles);
        testSuperClass(doubles);
        testInterface(doubles);
    }
}

private static int testSameClass(Object[] doubles) {
    long start = System.nanoTime();
    int count = 0;
    for (Object d : doubles) {
        if (d instanceof Double)
            count++;
    }
    long time = System.nanoTime() - start;
    System.out.printf("instanceof Double took an average of %.1f ns%n", 1.0 * time / doubles.length);
    return count;
}

private static int testSuperClass(Object[] doubles) {
    long start = System.nanoTime();
    int count = 0;
    for (Object d : doubles) {
        if (d instanceof Number)
            count++;
    }
    long time = System.nanoTime() - start;
    System.out.printf("instanceof Number took an average of %.1f ns%n", 1.0 * time / doubles.length);
    return count;
}

private static int testInterface(Object[] doubles) {
    long start = System.nanoTime();
    int count = 0;
    for (Object d : doubles) {
        if (d instanceof Serializable)
            count++;
    }
    long time = System.nanoTime() - start;
    System.out.printf("instanceof Serializable took an average of %.1f ns%n", 1.0 * time / doubles.length);
    return count;
}

最終的に印刷

instanceof Double took an average of 1.3 ns
instanceof Number took an average of 1.3 ns
instanceof Serializable took an average of 1.3 ns

「ダブル」を変更すると

    for(int i=0;i<doubles.length;i+=2)
        doubles[i] = "";

私は得る

instanceof Double took an average of 1.3 ns
instanceof Number took an average of 1.6 ns
instanceof Serializable took an average of 2.2 ns

注:私が変更した場合

if (d instanceof Double)

if (d != null && d.getClass() == Double.class)

性能は同じでした。

于 2012-09-12T11:15:30.770 に答える