一,引出思路
通过学习算法,我发现程序的性能很重要。好的代码或算法,它带来的效益是很大的。所以我就有感而发,希望可以对比两个程序模块或者算法的性能。衡量程序性能主要通过时间复杂度与空间复杂度,由于当今互联网界的发展,硬件内存越来越大,在这个"快"时代里,在保证空间够用的情况下,程序的时间复杂度比空间复杂度重要性更略胜一筹。
首先在IDEA环境中跑以下代码,你会发现诸多问题:
二、提出问题
1.两个不同的程序模块:
两个类用不同方法在对一组集合进行加和
private static String testStringAdd(){
String s=" ";
for(int i=0;i<10;i++){
s+=i;
}
return s;
}
private static String testStringBuilderAdd(){
StringBuilder sb=new StringBuilder();
for (int i=0;i<10;i++){
sb.append(i);
}
return sb.toString();
}
2.测试用例一
long t1=System.nanoTime();
testStringBuilderAdd();
long t2=System.nanoTime();
testStringAdd();
long t3=System.nanoTime();
System.out.println("testStringBuilderAdd: "+(t2-t1)+"纳秒");
System.out.println("testStringAdd: "+(t3-t2)+"纳秒");
3.测试用例二
long t1=System.nanoTime();
testStringAdd();
long t2=System.nanoTime();
testStringBuilderAdd();
long t3=System.nanoTime();
System.out.println("testStringBuilderAdd: "+(t3-t2)+"纳秒");
System.out.println("testStringAdd: "+(t2-t1)+"纳秒");
}
4.分析问题
同一个环境,同一段代码,只是交换了运行顺序,但是给出的结论却不一样。通过思考可以肯定的是有多种因素在代码运行时,影响了性能的比较,猜测可能影响性能的因素:
(1)次数太少(实验次数)
(2)执行时间短
(3)优化原因,编译器会自动分析,导致出现差错
(4)预热
(5)…
三,问题解决及优化
根据以上这些问题,进一步对程序性能比较提供一个相对公平的平台。
1.首先应该解决执行次数少,其次解决执行时间短问题,因此可以增加组数,且每组执行多次,这样便可以解决此问题。
用例一:
int iterations=100;
int group=5;
for (int i=0;i<group;i++){
long t1=System.nanoTime();
for(int j=0;j<iterations;j++){
testStringBuilderAdd();
}
long t2=System.nanoTime();
System.out.println("testStringBuilderAdd第"+i+"次耗时: "+(t2-t1)+"纳秒");
}
for (int i=0;i<group;i++){
long t3=System.nanoTime();
for(int j=0;j<iterations;j++){
testStringAdd();
}
long t4=System.nanoTime();
System.out.println("testStringAdd第"+i+"次耗时: "+(t4-t3)+"纳秒");
}
用例二:
int iterations=100;
int group=5;
for (int i=0;i<group;i++){
long t3=System.nanoTime();
for(int j=0;j<iterations;j++){
testStringAdd();
}
long t4=System.nanoTime();
System.out.println("testStringAdd第"+i+"次耗时: "+(t4-t3)+"纳秒");
}
for (int i=0;i<group;i++){
long t1=System.nanoTime();
for(int j=0;j<iterations;j++){
testStringBuilderAdd();
}
long t2=System.nanoTime();
System.out.println("testStringBuilderAdd第"+i+"次耗时: "+(t2-t1)+"纳秒");
}
当进行执行顺序调换时,取掉每组最大最小值时,可以看出现在使用StringBuilder方法进行加和时,更加好一点,但是为了性能比较更准确,选择继续处理刚刚影响因素。
2.java 程序是需要预热,才能达到最好状态的。这是因为 JVM 支持 JIT(Just In Time)的特性,因此应该对预热部分作出处理,避免内存数据加载等因素。
3.框架化,使得以后只需要写测试用例,便可以快速测试其他程序或算法
3.1利用注解标记出需要测试的方法
3.2利用注解配置测试的一些相关配置(三级配置(默认+类级别+方法))
3.3测试用例的自动发现