`
MauerSu
  • 浏览: 495824 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

消除Java应用中的Exception开销

 
阅读更多
源:http://blog.hesey.net/2013/11/eliminate-exception-overhead-in-java.html
评:


抛异常最大的消耗在于构造整个异常栈的过程,如果你的栈很深,特别是用了一些框架的话,这个开销基本是不可忽视的,之前做的一个优化显示当时应用中的一个异常使得整个应用的性能下降至少30%。
一、开销在哪

    最大开销的地方在这里,当你去new一个Exception的时候,会调用父类Throwable的构造函数,Throwable的构造函数中会调用native的fillInStackTrace(),这个方法就会构造整个异常栈了。

二、优化方案

    要优化这个地方,最简单的方案有两种:

    1、去掉异常栈构造

        如果你的Exception是自定义类型的,你很清楚什么情况哪行代码会抛出这个Exception,例如限流或者拒绝服务了。那么你可以给你的Exception Class重写fillInStackTrace()这个方法,搞一个空的实现就可以了,这样构造函数去调的时候就不会真正去调那个native的方法。抛异常的开销就没那么大了。


    2、去掉异常

        更推荐的做法是去看你到底是不是真的需要抛异常,把没有意义的异常去掉。例如之前见过有代码用异常流来实现正常的业务逻辑的,这种性能就很差了,因为你每次调用都会至少抛一个异常,并发量大的时候对性能影响非常大。

三、寻找异常

    有时候你可能无法直接找到到底哪个异常抛得最多,最典型的是引入了一个三方包,它里面自己抛了异常然后又自己catch住了,外面压根不知道里面居然还有这些破事儿。

    可以用perf top去看下us的开销,如果_ZN19java_lang_Throwable19fill_in_stack_traceE6HandleP6Thread这个排名很靠前,那就有必要看看异常的大头在哪里。

    最简单的用BTrace去跟一下Exception.<init>看构造Exception的栈是什么样的,然后排序汇总一下,一般就能看到什么Excetion最多,是谁抛的,然后有针对性地把它们去掉或者优化掉。

然后再压测你的应用,对CPU的开销会减少不少。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics