时间:2021-05-19
前言
程序的性能受到代码质量的直接影响。这次主要介绍一些代码编写的小技巧和惯例。虽然看起来有些是微不足道的编程技巧,却可能为系统性能带来成倍的提升,因此还是值得关注的。
慎用异常
在Java开发中,经常使用try-catch进行错误捕获,但是try-catch语句对系统性能而言是非常糟糕的。虽然一次try-catch中,无法察觉到她对性能带来的损失,但是一旦try-catch语句被应用于循环或是遍历体内,就会给系统性能带来极大的伤害。
以下是一段将try-catch应用于循环体内的示例代码:
@Test public void test11() { long start = System.currentTimeMillis(); int a = 0; for(int i=0;i<1000000000;i++){ try { a++; }catch (Exception e){ e.printStackTrace(); } } long useTime = System.currentTimeMillis()-start; System.out.println("useTime:"+useTime); }上面这段代码运行结果是:
useTime:10下面是一段将try-catch移到循环体外的代码,那么性能就提升了将近一半。如下:
@Test public void test(){ long start = System.currentTimeMillis(); int a = 0; try { for (int i=0;i<1000000000;i++){ a++; } }catch (Exception e){ e.printStackTrace(); } long useTime = System.currentTimeMillis()-start; System.out.println(useTime); }运行结果:
useTime:6使用局部变量
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。
下面是一段使用局部变量进行计算的代码:
@Test public void test11() { long start = System.currentTimeMillis(); int a = 0; for(int i=0;i<1000000000;i++){ a++; } long useTime = System.currentTimeMillis()-start; System.out.println("useTime:"+useTime); }运行结果:
useTime:5将局部变量替换为类的静态变量:
static int aa = 0; @Test public void test(){ long start = System.currentTimeMillis(); for (int i=0;i<1000000000;i++){ aa++; } long useTime = System.currentTimeMillis()-start; System.out.println("useTime:"+useTime); }运行结果:
useTime:94通过上面两次的运行结果,可以看出来局部变量的访问速度远远高于类成员变量。
位运算代替乘除法
在所有的运算中,位运算是最为高效的。因此,可以尝试使用位运算代替部分算术运算,来提高系统的运行速度。最典型的就是对于整数的乘除运算优化。
下面是一段使用算术运算的代码:
@Test public void test11() { long start = System.currentTimeMillis(); int a = 0; for(int i=0;i<1000000000;i++){ a*=2; a/=2; } long useTime = System.currentTimeMillis()-start; System.out.println("useTime:"+useTime); }运行结果:
useTime:1451将循环体中的乘除运算改为等价的位运算,代码如下:
@Test public void test(){ long start = System.currentTimeMillis(); int aa = 0; for (int i=0;i<1000000000;i++){ aa<<=1; aa>>=1; } long useTime = System.currentTimeMillis()-start; System.out.println("useTime:"+useTime); }运行结果:
useTime:10上两段代码执行了完全相同的功能,在每次循环中,都将整数乘以2,并除以2。但是运行结果耗时相差非常大,所以位运算的效率还是显而易见的。
提取表达式
在软件开发过程中,程序员很容易有意无意地让代码做一些“重复劳动”,在大部分情况下,由于计算机的高速运行,这些“重复劳动”并不会对性能构成太大的威胁,但若希望将系统性能发挥到极致,提取这些“重复劳动”相当有意义。
比如以下代码中进行了两次算术计算:
@Test public void testExpression(){ long start = System.currentTimeMillis(); double d = Math.random(); double a = Math.random(); double b = Math.random(); double e = Math.random(); double x,y; for(int i=0;i<10000000;i++){ x = d*a*b/3*4*a; y = e*a*b/3*4*a; } long useTime = System.currentTimeMillis()-start; System.out.println("useTime:"+useTime); }运行结果:
useTime:21仔细看能发现,两个计算表达式的后半部分完全相同,这也意味着在每次循环中,相同部分的表达式被重新计算了。
那么改进一下后就变成了下面的样子:
@Test public void testExpression99(){ long start = System.currentTimeMillis(); double d = Math.random(); double a = Math.random(); double b = Math.random(); double e = Math.random(); double p,x,y; for(int i=0;i<10000000;i++){ p = a*b/3*4*a; x = d*p; y = e*p; } long useTime = System.currentTimeMillis()-start; System.out.println("useTime:"+useTime); }运行结果:
useTime:11通过运行结果我们可以看出来具体的优化效果。
同理,如果在某循环中需要执行一个耗时操作,而在循环体内,其执行结果总是唯一的,也应该提取到循环体外。
例如下面的代码:
for(int i=0;i<100000;i++){ x[i] = Math.PI*Math.sin(y)*i;}应该改进成下面的代码:
//提取复杂,固定结果的业务逻辑处理到循环体外double p = Math.PI*Math.sin(y);for(int i=0;i<100000;i++){ x[i] = p*i;}使用arrayCopy()
数组复制是一项使用频率很高的功能,JDK中提供了一个高效的API来实现它。
/** * @param src the source array. * @param srcPos starting position in the source array. * @param dest the destination array. * @param destPos starting position in the destination data. * @param length the number of array elements to be copied. * @exception IndexOutOfBoundsException if copying would cause * access of data outside array bounds. * @exception ArrayStoreException if an element in the <code>src</code> * array could not be stored into the <code>dest</code> array * because of a type mismatch. * @exception NullPointerException if either <code>src</code> or * <code>dest</code> is <code>null</code>. */ public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);如果在应用程序中需要进行数组复制,应该使用这个函数,而不是自己实现。
下面来举例:
@Test public void testArrayCopy(){ int size = 100000; int[] array = new int[size]; int[] arraydest = new int[size]; for(int i=0;i<array.length;i++){ array[i] = i; } long start = System.currentTimeMillis(); for (int k=0;k<1000;k++){ //进行复制 System.arraycopy(array,0,arraydest,0,size); } long useTime = System.currentTimeMillis()-start; System.out.println("useTime:"+useTime); }运行结果:
useTime:59相对应地,如果在程序中,自己实现数组复制,其等价代码如下:
@Test public void testArrayCopy99(){ int size = 100000; int[] array = new int[size]; int[] arraydest = new int[size]; for(int i=0;i<array.length;i++){ array[i] = i; } long start = System.currentTimeMillis(); for (int k=0;k<1000;k++){ for(int i=0;i<size;i++){ arraydest[i] = array[i]; } } long useTime = System.currentTimeMillis()-start; System.out.println("useTime:"+useTime); }运行结果:
useTime:102通过运行结果可以看出效果。
因为System.arraycopy()函数是native函数,通常native函数的性能要优于普通函数。仅出于性能考虑,在程序开发时,应尽可能调用native函数。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
苹果今天推送了osx10.11elcapitanbeta4,本次更新重点也是改善性能和用户体验,想要体验的朋友可以自行下载升级哦! 用户可以通过MacApp
――测试关注于网站可最大限度影响企业的领域,关注于存在问题的领域,关注于能带来价值的领域。――测试关注于网站渠道的企业目标,而非只限于你所考虑的改善性能上。看起
――测试关注于网站可最大限度影响企业的领域,关注于存在问题的领域,关注于能带来价值的领域。――测试关注于网站渠道的企业目标,而非只限于你所考虑的改善性能上。看起
显卡发布后,AMD或NVIDIA会在第一时间发布新驱动予以支持,而在后续还会有不断的新驱动或改善性能,或修复Bug,或增加新功能,直至从支持列表中移除,成为一款
方法如下:1、将所有标签放在尽可能接近标签底部的位置,以保证页面在脚本运行之前完成解析尽量减少对整个页面下载的影响2、限制页面的总数也可以改善性能。每当页面解析