zoukankan      html  css  js  c++  java
  • 有助于改善性能的技巧

    1. 慎用异常

      在Java软件开发中,经常会使用try-catch进行错误捕获,但是,try-catch语句对系统性能而言是非常糟糕的。因此,应尽量避免将其应用在循环当中。

    2. 使用局部变量

      调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其它变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。

    3. 位运算代替乘除法

      在所有的运算中,位运算是最为高效的。因此,可以尝试使用位运算代替部分算术运算,来提高系统的运算速度。最典型的就是对于整数的乘除法运算优化。

    4. 替换switch

      关键字switch语句用于多条件判断,switch语句的功能类似于if-else语句,两者的性能也差不多。因此,不能说switch语句会降低系统的性能。但是,在绝大部分情况下,switch语句还是有性能提升空间的。

      来看下面的例子:

            int re = 0;
            for(int i=0;i<10000000;i++){
                re = switchInt(i);
            }
            protected int switchInt(int z){
                int i = z%10 + 1;
                switch(i){
                    case 1:return 3;
                    case 2:return 6;
                    case 3:return 7;
                    case 4:return 8;
                    case 5:return 10;
                    case 6:return 16;
                    case 7:return 18;
                    case 8:return 44;
                    default:return -1;
                }
            }

      上例中,就分支逻辑而言,这种switch模式的性能并不差。但是如果换一种全新的思路替代switch,实现相同的程序功能,那么性能就能有很大的提升空间。以下代码实现了与上例switch语句相同的功能:

            int re = 0;
            int[] sw = new int[]{0, 3, 6, 7, 8, 10, 16, 18, 44}; //替代switch逻辑
            for(int i=0;i<10000000;i++){
                re = arrayInt(sw, i);
            }
            protected int arrayInt(int[] sw, int z){
                int i = z%10 + 1;
                if(i<1||i>8)    //模拟switch的default
                    return -1;
                else
                    return sw[i];
            }

      以上代码采用全新的思路,使用一个连续的数组代替了switch语句。因为对数组的随机访问时非常快的,至少好于switch的分值判断,因此它的速度一定会快于原来的实现。通过实验,使用switch的语句相对耗时80ms,而使用数组的实现只相对耗时62ms。

    5. 一维数组代替二维数组

      由于数组的随机访问性能非常好,许多JDK类库,如Arraylist、Vector等都使用了数组作为其底层实现。但是,作为软件开发人员也必须知道,一维数组和二维数组的访问速度是不一样的。一维数组的访问速度要优于二维数组。因此,在性能敏感的系统中要使用二维数组的,可以尝试通过可靠的算法,将二维数组转为一维数组再进行处理,以提高系统的响应速度。

    6. 提取表达式

       在软件开发过程中,程序员很容易有意无意地让代码做一些“重复劳动”,在大部分情况下,由于计算机的高速运行,这些“重复劳动”并不会对性能构成太大的威胁,但若希望将系统性能发挥到极致,提取这些“重复劳动”相当有意义。尽可能让程序少做重复计算,尤其要关注在循环体内的代码,从循环体内提取重复的代码可以有效地提升系统性能。

    7. 展开循环

       与前面所介绍的优化技巧略有不同,展开循环是一种在极端情况下使用的优化手段,因为展开循环很可能会影响代码的可读性和可维护性,而这两者对软件系统来说也是极为重要的。但是,当性能问题成为系统的主要矛盾时,展开循环绝对是一种值得尝试的技术。

    一个普通的循环代码如下所示:

         int[] array = new int[9999999];
            for(int i=0;i<9999999;i++){
                array[i] = i;
            }

    展开循环后,类似以下格式:

            int[] array = new int[9999999];
            for(int i=0;i<9999999;i += 3){
                array[i] = i;
                array[i+1] = i+1;
                array[i+2] = i+2;
            }

      以上两段代码功能完全相同,但第二段代码进行了循环展开的优化,在一个循环体内处理了原代码段中的3个循环逻辑。运行以上两段代码,第一段代码相对耗时94ms,第二段代码相对耗时31ms,可见展开循环后,减少循环次数,对提升系统性能很有帮助。

    8. 布尔运算代替位运算

       虽然位运算的速度远远高于算术运算,但是在条件判断时,使用位运算替代布尔运算却是非常错误的选择。因为在条件判断时,Java会对布尔运算做相当充分的优化。在布尔表达式的计算中,只要表达式的值可以确定,就会立即返回,而跳过剩余子表达式的计算。若使用位运算(按位与、按位或)代替逻辑与和逻辑或,虽然位运算本身性能没有问题,但是位运算总是要将所有的子表达式全部计算完成后,再给出最终结果。因此,从这个角度说,使用位运算替代布尔运算会使系统进行很多无用计算。

    9. 使用arraycopy()

      数组复制是一项使用频率很高的功能,JDK中提供了一个高效的API来实现它:

    public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

      System.arraycopy()函数是native函数,通常native函数的性能要优于普通函数,仅出于性能考虑,在软件开发时,应尽可能调用native函数。

    10. 使用Buffer进行I/O操作

      除NIO外,使用java进行I/O操作有两种基本方式:

    1. 使用基于InputStream和OutputStream的方式
    2. 使用Writer和Reader

      无论使用哪种方式进行文件的I/O,如果能合理地使用缓冲,就能有效地提高I/O的性能。

     11. 使用clone()代替new

      在Java中新建对象实例最常用的方法是使用new关键字。JDK对new关键字的支持非常好,使用new关键字创建轻量级对象时,速度非常快。但是,对于重量级对象,由于对象在构造函数中可能会进行一些复杂而且耗时的操作,因此,构造函数的执行时间可能会比较长。这就导致了创建对象的耗时很长,同时也使得系统无法在短期内获得大量的实例。为了解决这个问题,可以使用Object.clone()方法。

      Object.clone()方法可以绕过对象构造函数,快速复制一个对象实例。由于不需要调用对象构造函数,因此,clone()方法不会受到构造函数性能的影响,能够快速生成一个实例。但是,在默认的情况下,clone()方法生成的实例只是原对象的浅拷贝。如果需要深拷贝,则需要重新实现clone()方法。

     12. 静态方法替代实例方法

      使用关键字static声明的方法为静态方法。在Java中,由于实例方法需要维护一张类似虚函数表的结构,以实现对多态的支持。与静态方法相比,实例方法的调用需要更多的资源。因此,对于一些常用的工具类方法,没有对其进行重载的必要,那么就可以将它们声明为static,便可以加速方法的调用。对于一些工具类,应该使用static方法实现,这样不仅可以加速函数调用的速度,同时,调用static方法也不需要生成类的实例,比调用实例方法更为方便、易用。

  • 相关阅读:
    7.21 高博教育 数组 内存
    【基础扎实】Python操作Excel三模块
    PAT 甲级 1012 The Best Rank
    PAT 甲级 1011  World Cup Betting
    PAT 甲级 1010 Radix
    链式线性表——实验及提升训练
    循环程序设计能力自测
    链表应用能力自测
    PAT 甲级 1009 Product of Polynomials
    1008 Elevator (20分)
  • 原文地址:https://www.cnblogs.com/gaopeng527/p/4904474.html
Copyright © 2011-2022 走看看