问下面哪个方法计算速度更快
public class FFFtest {
public static void main(String[] args) {
int[] a=new int[1000];
int[] b=new int[10000000];
long start = System.currentTimeMillis();
//method 1
for(int i=0;i<1000;i++){
for(int j=0;j<10000000;j++){
a[i]++;
}
}
long end = System.currentTimeMillis();
System.out.println(end-start);
start=System.currentTimeMillis();
//method 2
for(int i=0 ;i<10000000;i++){
for(int j=0;j<1000;j++){
b[i]++;
}
}
end = System.currentTimeMillis();
System.out.println(end-start);
}
}
输出:
25616
21736
结果表示,第二中更快一些,求解释!!!
阿里巴巴 java
------解决方案--------------------
测试1:将赋值语句注释
public static void main(String[] args) {
int[] a=new int[1000];
int[] b=new int[10000000];
long start = System.currentTimeMillis();
//method 1
for(int i=0;i<1000;i++){
for(int j=0;j<10000000;j++){
// a[i]++;
}
}
long end = System.currentTimeMillis();
System.out.print(end-start+"\t");
start=System.currentTimeMillis();
//method 2
for(int i=0 ;i<10000000;i++){
for(int j=0;j<1000;j++){
// b[i]++;
}
}
end = System.currentTimeMillis();
System.out.println(end-start);
}
测试结果:
3704 4095
3625 3860
3609 3877
3609 4001
测试2:恢复赋值(同楼主代码)
测试结果:
23616 22096
23048 21986
24164 22495
23532 22175
结果分析:
1、通过测试1(仅循环切换耗时)可以证明6楼的所说,第一段代码从内层循环切到外层的次数为 1000次;第二段代码从内层循环切到外层的次数为10000000次,所以切换多的耗时多
2、通过测试2看到加上赋值后第一段代码明显耗时明显增加,两段代码赋值次数都一样,但是第一段代码每一个数组元素都是从1-10000000赋值,存大赋值大数据
所以我觉得整体来说大赋值大数据耗时会比较多
------解决方案--------------------
这题的理性认识应该是第一个比较快。
因为a[i]和b[i]都是一个内存查找的动作,而a[i]只查找了1000次,b[i]却查找了10000000次。a[i]更多地击中了CPU的缓存(快),而b[i]更多地进行了内存查找(慢)。
于是乎这就是一个micro benchmark的问题了。Java的micro benchmark是很难的,也没有什么绝对公平的方法。难点在于JVM的JIT。
对于进行micro benchmark的方法,首先要进行预热,其次要进行统计。
预热的概念是让JVM先行运行该方法若干次(关键词:compile threshold),使其JIT对方法进行优化和编译。
统计的意思是运行多次测试,取平均值、中值、标准差等数据进行综合比较。
另外要注意的一点是,绝对不能在同一个程序里面测试两种方法。要编译测试两个方法的不同版本分别进行测试,否则会有干扰。
以下是我的测试方法:这个测试里面我没有用统计方法,因为结果已经很明显了:方法一比方法二快了2.5倍左右
package test;
public class Test {
static int[] a = new int[100];
static int[] b = new int[100000];
public static void main(final String[] args) throws Exception {
// warm up
for (int i = 0; i < 5000; i++)
method2();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++)
method2();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
static void method1() {
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100000; j++) {
a[i]++;
}