我正在阅读 Java 8 中的新功能,其中之一是新的 Arrays.parallelSort() 方法。我做了一些测试,对 double 组和一个字符串进行排序,对于字符串,parallelSort 慢得多。
下面是一个字符串测试方法的内容:
final int size = 10000;
final String[] values1 = new String[size];
final String[] values2 = new String[size];
for (int i = 0; i < size; i++) {
values1[i] = Integer.toString(i);
values2[i] = values1[i];
}
Collections.shuffle(Arrays.asList(values1));
Collections.shuffle(Arrays.asList(values2));
final Comparator<String> comparator = (o1, o2) -> o2.compareTo(o1);
long startTimeInNano = System.nanoTime();
Arrays.sort(values1, comparator);
long endTimeInNano = System.nanoTime();
System.out.println("Arrays.sort: totalTimeInMicro= " + ((endTimeInNano - startTimeInNano)/1000));
//parallel sort with java 8
startTimeInNano = System.nanoTime();
Arrays.parallelSort(values2,comparator);
endTimeInNano = System.nanoTime();
System.out.println("Arrays.parallelSort: totalTimeInMicro= " + ((endTimeInNano - startTimeInNano)/1000));
结果是:
Arrays.sort: totalTimeInMicro= 11993
Arrays.parallelSort: totalTimeInMicro= 89823
我还在另一台计算机上尝试了这段代码,结果是一样的(25608 对 808660)。我运行测试的计算机有一个 i5-2500 CPU。您知道我为什么会得到这种结果吗?
这个基准测试几乎没有告诉您任何信息。微基准测试最重要的事情是
- 让 JIT 有机会通过多次运行测试来优化代码
- 使用不同的输入尺寸
- 打印一些结果,以防止 JIT 优化整个调用
还有一些要考虑的要点 - 事实上,很多要考虑的要点。你应该咨询How do I write a correct micro-benchmark in Java?了解更多信息。
要获得真正“深刻”的信息,您应该使用像 Caliper 这样的工具或 JMH .但即使不费吹灰之力,也可以创建一个微基准,粗略地显示实际性能如何。因此,一种最简单的微基准测试形式可能如下所示:
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
public class ParallelSortSpeedTest
{
public static void main(String[] args)
{
for (int size=100000; size<=1000000; size+=100000)
{
final String[] values1 = new String[size];
final String[] values2 = new String[size];
for (int i = 0; i < size; i++) {
values1[i] = Integer.toString(i);
values2[i] = values1[i];
}
Collections.shuffle(Arrays.asList(values1));
Collections.shuffle(Arrays.asList(values2));
final Comparator<String> comparator = (o1, o2) -> o2.compareTo(o1);
testSort(values1, comparator);
testParallelSort(values2, comparator);
}
}
private static void testSort(
String array[], final Comparator<String> comparator)
{
long startTimeInNano = System.nanoTime();
Arrays.sort(array, comparator);
long endTimeInNano = System.nanoTime();
System.out.println("Arrays.sort : totalTimeInMicro= " +
((endTimeInNano - startTimeInNano)/1000)+", first "+array[0]);
}
private static void testParallelSort(
String array[], final Comparator<String> comparator)
{
long startTimeInNano = System.nanoTime();
Arrays.parallelSort(array, comparator);
long endTimeInNano = System.nanoTime();
System.out.println("Arrays.parallelSort: totalTimeInMicro= " +
((endTimeInNano - startTimeInNano)/1000)+", first "+array[0]);
}
}
考虑到启动和运行 JMH 基准测试的工作量与结果的可靠性之间的权衡,这是一个合理的选择。这个测试会打印类似的东西
...
Arrays.sort : totalTimeInMicro= 530669, first 999999
Arrays.parallelSort: totalTimeInMicro= 158227, first 999999
至少表明并行排序应该更快。