当前位置: 首页 > 科技观察

JAVA异常对性能的影响

时间:2023-03-11 22:03:57 科技观察

在为OneAPM客户做技术支持的时候,经常会看到很多客户没有意识到的异常。排除这些异常后,代码运行速度比以前快多了。这让我们猜测在代码中使用异常会带来显着的性能开销。因为异常是错误处理的重要组成部分,放弃的可能性不大,所以我们需要衡量异常处理对性能的影响。我们可以通过一个实验来看看异常处理对性能的影响。实验我的实验基于一段随机抛出异常的简单代码。从科学的角度来看,这并不是一个完全准确的测量,我不知道HotSpot编译器会对运行的代码做些什么。但无论如何,这段代码应该给我们一些基本的洞察力。结果很有趣:抛出和捕获异常的成本似乎极低。在我的例子中,每次异常大约需要0.02毫秒。除非你真的抛出太多异常(我们指的是100,000或更多),否则这几乎可以忽略不计。虽然这些结果表明异常处理本身不会影响代码性能,但它没有解决以下问题:谁应对异常的巨大性能影响负责?我显然错过了一些重要的东西。转念一想,我意识到我遗漏了异常处理的一个重要部分。我没有考虑到异常发生时你做了什么。在大多数情况下,您很可能不仅仅是在捕获异常!这就是问题所在:通常,您试图补充问题并仍然使应用程序对最终用户有效。所以我缺少的是:““为处理异常而执行的补充代码”。根据补充代码,性能损失可能会变得相当显着。在某些情况下,这可能意味着重试与服务器的连接,在其他情况下,这可能意味着使用默认的回退方案,该方案提供的解决方法肯定会导致性能非常差。这似乎很好地解释了我们在许多情况下看到的行为。但是,我并不认为分析到这里就万事大吉了,而是感觉这里还少了点什么。Stacktrace我对这个问题还是比较好奇的,所以在收集stracktraces的时候监测了性能的变化情况。经常发生的事情应该是这样的:记下异常及其堆栈跟踪,并尝试找出问题所在。为此,我修改了代码,额外收集了异常的stracktrace。这极大地改变了局势。收集异常的stracktraces对性能的影响是简单捕获并抛出异常的10倍。因此,虽然stracktrace有助于了解问题发生的位置(以及可能的原因),但会降低性能。由于我们不是在谈论stracktrace,因此这里的影响通常非常大。在大多数情况下,我们会在多个级别抛出和捕获异常。让我们看一个简单的示例:Web服务客户端连接到服务器。首先,存在Java库级别的连接失败异常。之后会出现框架层面的客户端失败异常,以后可能会出现应用层面的业务逻辑调用失败异常。到目前为止,总共需要收集三个stracktraces。在大多数情况下,您可以从日志文件或应用程序输出中看到这些stracktrace,而编写这些长stracktrace通常也会对性能产生影响。结论首先,由于性能影响,丢弃异常不是一个好主意。异常有助于提供一致的方法来解决运行时问题并帮助编写干净的代码。但是我们应该跟踪代码中抛出的异常数量,它们会对性能产生重大影响。所以OneAPM会跟踪默认抛出的异常——在很多情况下,人们会对代码中出现的异常以及解决这些异常时的性能损失感到惊讶。其次,虽然使用异常是有益的,但您应该避免捕获太多的stracktraces。异常应该是为异常情况而设计的,在使用的时候要牢记这个原则。当然,如果您不想遵循良好的编程习惯,Java语言会通过让您知道这样做会使您的程序运行得更快来鼓励您这样做。