正文内容 评论(0

Java的异常处理对于性能的影响
2015-04-22 11:29:00  出处:IT168   编辑:快科技     评论(0)点击可以复制本篇文章的标题和链接

在对OneAPM的客户做技术支持时,我们常常会看到很多客户根本没意识到的异常。在消除了这些异常之后,代码运行速度与以前相比大幅提升。这就让我们产生一种猜测,也就是在代码里面使用异常会带来显著的性能开销。不过由于异常是错误情况处理的重要组成部分,完全摒弃也是不太可能的。那么异常处理对于性能影响到底有多大呢?我们来做个实验看看。

实验

我的实验基于一段随机抛出异常的简单代码。从科学的角度,这并非真正深入的测量;而且我们也并不了解HotSpot编译器会对运行中的代码做何动作。但无论如何,这段代码应该能够让我们了解一些基本情况:

结果

结果很有意思。抛出与捕获异常的代价似乎极低。在我的例子里,大约是每个异常0.02毫秒。除非你真的抛出太多异常(我们说的是10万次或者更多),否则这一点基本都可忽略。

尽管这些结果显示出异常处理本身并不影响代码性能,但却并未解决下面这个问题:异常对性能的巨大影响该由谁负责?因此我明显遗漏了什么重要的地板供需。

重新想了一下,我意识到自己遗漏了异常处理的一个重要部分。我没考虑到异常发生时你做了什么。在多数情况下你很有可能不仅仅是捕获异常,而问题就在这里。

一般情况下,你会试图对问题进行补充,并让应用在最终用户那里仍能发挥功能。所以我遗漏的就是为了处理异常而执行的补充代码。按照补充代码的不同,性能损失可能变得相当显著。在某些情况下这可能意味着重试连接到服务器,在其他情况下则可能意味着使用默认的后退解决方案,而这种方案提供的解决办法却会带来差得多的性能。

对于我们在很多情况下看到的行为,这似乎给出了很好的解释。不过我却不觉得分析已经万事大吉,而是感到这里还遗漏了别的什么东西。

栈轨迹

对此问题,我仍颇为好奇,为此审视了收集栈轨迹时情况有何变化。经常发生的也不过如此:

记下异常及其栈轨迹,以尝试找出问题为何。

为此我修改了代码,额外收集了异常的栈轨迹。这让情况显著改变。对异常的栈轨迹的收集,其性能影响要比单纯捕获并抛出异常高出10倍。因此尽管栈轨迹有助于理解哪里发生了问题(有可能还有助于理解为何发生问题),但却存在性能损失。

由于我们谈论的并非一条栈轨迹,所以此处的影响往往非常之大。多数情况下,我们都要在多个层次上抛出并捕获异常。我们看一个简单的例子:

Web服务客户端连接到服务器。首先,Java库级别上存在一个连接失败异常。此后会有框架级别上的客户端失败异常,再以后可能还会有应用层次上的业务逻辑调用失败异常。到现在为止,总共要搜集三条栈轨迹。

多数情况下,你都能从日志文件或者应用输出中看到这些栈轨迹。写入这些较长的栈轨迹也带来了性能影响。如果你定期查看日志文件的话,至少你应该都能看到它们并做出反应——你真的定期查看日志文件,对吧?

结论

因为存在性能影响而把异常弃之不用并非良策。异常有助于提供一种一致的方式来解决运行时问题,并且有助于写出干净的代码。但却需要对代码中抛出的异常数量进行跟踪,它们可能存在显著的性能影响。在OneAPM中我们默认要对所抛出的异常进行跟踪——而在很多情况下人们都会对代码中发生的异常以及在解决这些异常时的性能影响感到吃惊不已。

不过尽管使用异常很有裨益,您也应避免捕获过多的栈轨迹。异常应该是为异常的情况而设计的,使用时也应该牢记这一原则。但是,万一您不想遵从好的编程习惯,Java语言就会让您知道,那样做可以让您的程序运行得更快,从而鼓励您去那样做。

责任编辑:

  • 支持打赏
  • 支持0

  • 反对

  • 打赏

文章价值打分

当前文章打分0 分,共有0人打分
  • 分享好友:
  • |
本文收录在
#软件

  • 热门文章
  • 换一波

  • 好物推荐
  • 换一波

  • 关注我们

  • 微博

    微博:快科技官方

    快科技官方微博
  • 今日头条

    今日头条:快科技

    带来硬件软件、手机数码最快资讯!
  • 抖音

    抖音:kkjcn

    科技快讯、手机开箱、产品体验、应用推荐...