제목은 왜 정렬되지 않은 배열보다 정렬 된 배열을 처리하는 것이 더 빠릅니까?
이것도 분기 예측 효과입니까? 주의 : 여기 정렬 된 배열의 처리 속도 가 느립니다 !!
다음 코드를 고려하십시오.
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);
...
}
이것은 내 컴퓨터에서 약 720의 값을 인쇄합니다.
이제 컬렉션 정렬 호출을 활성화하면 그 값이 142로 떨어집니다. 왜?!?
결과 는 결정적이며 반복 횟수 / 시간을 늘려도 변경되지 않습니다.
Java 버전은 1.8.0_71 (Oracle VM, 64 비트)이며 Windows 10, Eclipse Mars의 JUnit 테스트에서 실행됩니다.
최신 정보
연속적인 메모리 액세스와 관련이있는 것 같습니다 (순차적으로 액세스되는 이중 객체와 임의의 순서로 액세스 됨). 약 10k 이하의 어레이 길이에서 효과가 사라지기 시작합니다.
/**
* 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
*/