Tytuł odnosi się do Dlaczego szybciej przetwarzać posortowaną tablicę niż nieposortowaną?
Czy to też jest efekt przewidywania gałęzi? Uwaga: tutaj przetwarzanie posortowanej tablicy jest wolniejsze !!
Rozważ następujący kod:
private static final int LIST_LENGTH = 1000 * 1000;
private static final long SLOW_ITERATION_MILLIS = 1000L * 10L;
@Test
public void testBinarySearch() {
Random r = new Random(0);
List<Double> list = new ArrayList<>(LIST_LENGTH);
for (int i = 0; i < LIST_LENGTH; i++) {
list.add(r.nextDouble());
}
//Collections.sort(list);
// remove possible artifacts due to the sorting call
// and rebuild the list from scratch:
list = new ArrayList<>(list);
int nIterations = 0;
long startTime = System.currentTimeMillis();
do {
int index = r.nextInt(LIST_LENGTH);
assertEquals(index, list.indexOf(list.get(index)));
nIterations++;
} while (System.currentTimeMillis() < startTime + SLOW_ITERATION_MILLIS);
long duration = System.currentTimeMillis() - startTime;
double slowFindsPerSec = (double) nIterations / duration * 1000;
System.out.println(slowFindsPerSec);
...
}
Spowoduje to wyświetlenie wartości około 720 na moim komputerze.
Jeśli teraz aktywuję wywołanie sortowania kolekcji, ta wartość spadnie do 142. Dlaczego?!?
Wyniki są rozstrzygające, nie zmieniają się, jeśli zwiększę liczbę iteracji / czas.
Wersja Java to 1.8.0_71 (Oracle VM, 64 bit), działająca pod Windows 10, test JUnit w Eclipse Mars.
AKTUALIZACJA
Wydaje się, że jest związany z ciągłym dostępem do pamięci (podwójne obiekty dostępne w kolejności sekwencyjnej vs w kolejności losowej). Efekt zaczyna znikać dla mnie dla tablic o długości około 10k i mniej.
Dzięki asyliom za dostarczenie wyników :
/**
* Benchmark Mode Cnt Score Error Units
* SO35018999.shuffled avgt 10 8.895 ± 1.534 ms/op
* SO35018999.sorted avgt 10 8.093 ± 3.093 ms/op
* SO35018999.sorted_contiguous avgt 10 1.665 ± 0.397 ms/op
* SO35018999.unsorted avgt 10 2.700 ± 0.302 ms/op
*/