zoukankan      html  css  js  c++  java
  • 系统性能调优(6)Java异常处理性能优化

    执行一个catch代码块和抛出一个异常花费是很高的,这个过程中的性能损耗主要是由于当创建一个异常时要获得线程栈的一个快照。抛出异常首先要创建一个新的对象Throwable类的构造函数调用名为fillInStackTrace的方法,fillInStackTrace方法检查堆栈,收集调用跟踪信息。由于在处理过程中创建了一个新的对象,所以说只要有异常被抛出,JVM就必须调整调用堆栈,系统资源开销也就增大了。

    1、使编译器和运行时最优化,将几个方法调用放在一个try/catch块中,而不是为每个方法调用各自使用try/catch

    	try{ 
    	    Some.method1();  
    	}catch(method1Exception e){ 
    	    handle exception 1 
    	}
    	try{ 
    	    Some.method2();  
    	}catch(method2Exception e){ 
    	    handle exception 2  
    	}
    	try{ 
    	    Some.method3();  
    	}catch(method3Exception e){ 
    	    handle exception 3  
    	}
    

    应当优化为如下代码

    	try{ 
    		Some.method1(); 
    	    Some.method2(); 
    	    Some.method3(); 
    	}catch(method1Exception e){ 
    	    handle exception 1 
    	}catch(method2Exception e){ 
    	    handle exception 2 
    	}catch(method3Exception e){ 
    	    handle exception 3 
    	}
    


    2、异常只能用于错误处理,不应该用来控制程序流程。

    public class Test {
        int value;
    
    
        public int getValue() {
        	return value;
        }
    
        public void reset() {
        	value = 0;
        }
    
        // Calculates without exception
        public void method1(int i) {
        	value = ((value + i) / i) << 1;
        	// Will never be true
        	if ((i & 0xFFFFFFF) == 1000000000) {
        		System.out.println("You'll never see this!");
        	}
        }
    
        // Could in theory throw one, but never will
        public void method2(int i) throws Exception {
        	value = ((value + i) / i) << 1;
        	// Will never be true
        	if ((i & 0xFFFFFFF) == 1000000000) {
        		throw new Exception();
        	}
        }
    
        // This one will regularly throw one
        public void method3(int i) throws Exception {
        	value = ((value + i) / i) << 1;
        	// i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
        	// an AND operation between two integers. The size of the number plays
        	// no role. AND on 32 BIT always ANDs all 32 bits
        	if ((i & 0x1) == 1) {
        		throw new Exception();
        	}
        }
    
        public static void main(String[] args) {
        	int i;
        	long l;
        	Test t = new Test();
    
        	l = System.currentTimeMillis();
        	t.reset();
        	for (i = 1; i < 100000000; i++) {
        		t.method1(i);
        	}
        	l = System.currentTimeMillis() - l;
        	System.out.println(
        		"method1 took " + l + " ms, result was " + t.getValue()
        	);
    
        	l = System.currentTimeMillis();
        	t.reset();
        	for (i = 1; i < 100000000; i++) {
        		try {
        			t.method2(i);
        		} catch (Exception e) {
        			System.out.println("You'll never see this!");
        		}
        	}
        	l = System.currentTimeMillis() - l;
        	System.out.println(
        		"method2 took " + l + " ms, result was " + t.getValue()
        	);
    
        	l = System.currentTimeMillis();
        	t.reset();
        	for (i = 1; i < 100000000; i++) {
        		try {
        			t.method3(i);
        		} catch (Exception e) {
        			// Do nothing here, as we will get here
        		}
        	}
        	l = System.currentTimeMillis() - l;
        	System.out.println(
        		"method3 took " + l + " ms, result was " + t.getValue()
        	);
        }
    }
    

    上段代码首先创建了三个方法,在这三个方法当中第一个没有抛出异常,第二个当符合条件的时候抛出异常,第三个和第二个一样。(实际上三个方法中value的存在就是为了延长程序的运行时间,没有实际意义。)从运行结果可以看出来抛出异常是相当消耗资源的,尽管有时不出现异常时性能尚可,但是依然不建议用异常控制程序流程。

    不做多余的的事情就是调优,保证功能实现的情况下最低程度的减少开销就是优化。

    原创文章,转载请注明出处:http://www.cnblogs.com/beijiguangyong/
  • 相关阅读:
    题解报告——垃圾陷阱
    后缀自动机
    计算几何之凸包
    平衡树——treap
    图论--最小费用最大流(MCMF)
    很重要的吐槽!
    图论--网络流初步(最大流,增广路)
    字符串--Trie树(字典树)
    图论--Tarjan求强联通分量
    数据结构--堆
  • 原文地址:https://www.cnblogs.com/beijiguangyong/p/3172918.html
Copyright © 2011-2022 走看看