抛出异常–缓慢而丑陋

这篇文章是关于历史经验以及最近应用的性能优化技术的。 几年前,我在特定的应用程序中发誓,我不得不发现隐藏在真正聪明的工程“技术”之下的无证行为。

它是一个典型的用于发票的单片Java EE应用程序。 最好忘记确切的代码,但是我记得开发人员已经找到了一种真正聪明的方法来控制业务流程。

流程的一部分通常是无休止的if-then-else混乱,但使事情更加“令人兴奋”的是,这些检查的一些随机元素被埋入了自定义java.lang.RuntimeException处理机制中。 因此,您可能具有类似于以下内容的代码:

if (invoice.overdue()) {if (invoice.getCustomer().isKeyCustomer())throw new InvoiceOverdueException(InvoiceOverdueException.KEY_CUSTOMER);elsedoSomething();
}
else {if (invoice.getDueAmount() > BIG_AMOUNT)if (invoice.getCustomer().isKeyCustomer())//be silentelsethrow new InvoiceExceededException(invoice.getDueAmount());
}

并非像上述那样简短易懂的块,而是在整个应用程序中散布了数千行代码。

我想你可能同意我的观点,这是使自己不可或缺的一种好方法。 有人会以一种疯狂的方式来理解应用程序为什么会如此。

我回想起最近的Plumbr优化任务带来的经验。 我想说我们的代码没有使用前面案例描述的异常,但是不幸的是,这并非完全正确。 一个特定的方法仍然在代码的常规流程中构造并抛出RuntimeException 。 由于这个特定模块的性能异常,我只发现了这个孤独的反派。

通常,仅在遇到意外问题时才会引发异常。 因此,我们不希望每个线程每秒抛出数千个异常。 但是像我一样,您可能会发现一种对异常事件使用异常的方法。

我之所以只找到罪魁祸首,是因为这是特定图形遍历算法中经常使用的代码块,因此从中挤出最后一毫秒至关重要。 立即删除异常处理使此代码块的完成速度提高了100倍以上。

这可能使您想知道–为什么异常处理速度很慢? 最慢的部分与构造异常有关。 或者,更确切地说,是java.lang.Throwable的任何子类。

如果您还记得的话,所有构造函数都会通过调用super()来调用对超类默认构造函数的调用。 如果您未自行指定此调用,则编译器会友好地将其添加到字节码本身中。 无论如何,当查看java.lang.Throwable源代码时,您会看到答案盯着您:

public Throwable() {fillInStackTrace();}public synchronized Throwable fillInStackTrace() {if (stackTrace != null ||backtrace != null /* Out of protocol state */ ) {fillInStackTrace(0);stackTrace = UNASSIGNED_STACK;}return this;}private native Throwable fillInStackTrace(int dummy);

因此,每次创建新的Throwable()时,最终都会通过本机调用填充整个堆栈跟踪。 如果您不认为这很慢,请执行以下jmh微基准测试,以验证创建异常的费用比构造常规对象的费用高数百倍:

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class NewExceptionTest {@GenerateMicroBenchmarkpublic Object baseline() {return new Object();}@GenerateMicroBenchmarkpublic Object exceptional() {return new RuntimeException();}
}
Benchmark                          Mode Thr    Cnt  Sec         Mean   Mean error    Units
j.NewExceptionTest.baseline        avgt   1      5    5        3.275        0.029  nsec/op
j.NewExceptionTest.exceptional     avgt   1      5    5     1329.266        8.675  nsec/op

总而言之,在特殊情况下,名称应表示例外。 如果您开始滥用该概念,那么您要么使代码不可读,要么开始遭受性能问题的困扰。 至少,我保证您会从中获得大量的负面因果报应。

参考: 抛出异常–我们的JCG合作伙伴 Nikita Salnikov Tarnovski在Plumbr Blog博客上缓慢而丑陋 。

翻译自: https://www.javacodegeeks.com/2013/08/throwing-exceptions-slow-and-ugly.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367528.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信号与线性系统翻转课堂笔记9——傅里叶变换概念

信号与线性系统翻转课堂笔记9——傅里叶变换 The Flipped Classroom9 of Signals and Linear Systems 对应教材:《信号与线性系统分析(第五版)》高等教育出版社,吴大正著 一、要点 (1,重点)…

abstract修饰符

1、一个类不能同时被 abstract 和 final 修饰。 2、如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。 3、抽象类可以包含抽象方法和非抽象方法。 4、抽象方法是由子类来实现。 5、抽象方法不能被声明成 final 和 static。 6、任…

埃及分数问题(带乐观估计函数的迭代加深搜索算法-IDA*)

#10022. 「一本通 1.3 练习 1」埃及分数 【题目描述】 在古埃及,人们使用单位分数的和(形如 $\dfrac{1}{a}​$​​ 的,$a$ 是自然数)表示一切有理数。如:$\dfrac{2}{3} \dfrac{1}{2} \dfrac{1}{6}​$​​&#xff0c…

玩转Jquery中的动画效果(animate方法)

jQuery 动画 - animate() 方法jQuery animate() 方法用于创建自定义动画。语法:$(selector).animate({params},speed,callback);必需的 params 参数定义形成动画的 CSS 属性。可选的 speed 参数规定效果的时长。它可以取以下值:"slow"、"…

matlab 等分矩阵,用matlab根据列拆分矩阵.

使用logical indexingBA(A(:,end)10,:);CA(A(:,end)2,:);回报>> BB 1 4 2 5 102 1 5 6 10>> CC 2 4 5 6 22 3 5 4 2编辑:在回复丹的评论这里是一般情况的扩展e unique(A(:,end));B cell(size(e));for k 1:numel(e)B{k} A(A(:,end)e(k),:);end或者更…

点击网页跟踪php代码的工具,使用ltrace工具跟踪PHP库函数调用的方法

本文实例讲述了使用ltrace工具跟踪PHP库函数调用的方法。分享给大家供大家参考,具体如下:可能大家已经很熟悉使用strace来跟踪系统调用,今天介绍一个跟踪库函数的利器ltrace比如我有这么一段PHP代码test.php:$y 1380;$arr array…

HDU 2841 Visible Trees(容斥)题解

题意:有一块(1,1)到(m,n)的地,从(0,0)看能看到几块(如果两块地到看的地方三点一线,后面的地都看不到)。 思路:…

Jquery获取服务器端控件ID的方法

<asp:textbox runat"server" id"txtMessage" textmode"SingleLine">some strings here...</asp:textbox>但是当这段代码输出到客户端时就变成了这样&#xff1a;<input name"ctl00$txtMessage" id"ctl00_txtMessa…

安全地创建和存储密码

几乎每次涉及用户配置文件时&#xff0c;都必须管理用户凭据&#xff0c;从而能够创建和存储用户密码。 通常应该使用散列密码和盐分密码来准备数据库公开和通过使用Rainbow表进行散列反转的密码。 但是&#xff0c;找到以明文形式存储的密码并不少见&#xff08;很不幸&#…

Swift Defer 延迟调用

1、Defer 在一些语言中&#xff0c;有 try/finally 这样的控制语句&#xff0c;比如 Java。这种语句可以让我们在 finally 代码块中执行必须要执行的代码&#xff0c;不管之前怎样的兴风作浪。在 Swift 2.0 中&#xff0c;Apple 提供了 defer 关键字&#xff0c;让我们可以实现…

mysql strtok,strtok()和strtok_r()

下面的说明摘自于最新的Linux内核2.6.29&#xff0c;说明了strtok()这个函数已经不再使用&#xff0c;由速度更快的strsep()代替/** linux/lib/string.c** Copyright (C) 1991, 1992 Linus Torvalds*//** stupid library routines.. The optimized versions should generally b…

from 下拉框多个值提交_Git commit 多行信息提交

git commit可接受多个消息标志(-m)来允许多行提交原文地址&#xff1a;https://www.stefanjudis.com/today-i-learned/git-commit-accepts-several-message-flags-m-to-allow-multiline-commits/原文作者&#xff1a;Stephan Schneider在命令行上使用git时&#xff0c;您可能已…

处理缓慢的资源泄漏

使用Java监视器查找资源泄漏 查找缓慢的资源泄漏是使应用程序服务器长时间保持正常运行的关键。 在这里&#xff0c;我解释了如何使用Java监视器来发现缓慢的资源泄漏&#xff0c;以及如何验证它们是实际的泄漏&#xff0c;而不仅仅是额外的预分配到某些HTTP连接器或数据库池中…

jquery简单实现点击弹出层效果实例

先看效果图&#xff1a;完整例子&#xff1a; <!-- 渐变弹出层 --><div id"race"><a href"#">点击</a></div><div id"racePop" class"raceShow">这里是弹出层效果</div> <script type&q…

Openfire源码阅读(一)

本篇先分析openfire源码的主要流程&#xff0c;模块细节后续再继续分析&#xff1b; 一、简介&#xff1a; Openfire是开源的实时协作服务器&#xff08;RTC&#xff09;&#xff0c;它是基于公开协议XMPP&#xff08;RFC-3920&#xff09;&#xff0c;并在此基础上实现了XMPP-…

常见的linux命令及其翻译

常见的linux指令 1、ls ll 查看文件信息 2、cd 切换工作目录 cd 或 cd ~ 切换到/home/用户目录 cd. 切换到当前目录 cd.. 切换到上级目录 cd- 切换入上次所在的目录 3、clear 或 ctrl l 清屏 4、pwd 显示当前路径 5、mkdir 创建目录 6、rm 删除文件 rm -r 删除文件夹 7、cp 拷…

php 查询方法all,获取多条:all静态方法

查询多条数据&#xff1a;all( )方法all方法与前节课学习的get方法都是静态方法&#xff0c;可用模型类直接访问2. 源码&#xff1a;/*** 查找所有记录* access public* param mixed $data 主键列表或者查询条件(闭包)* param array|string $with 关联预查询* param b…

Google GSON入门

在Java世界中&#xff0c;JSON已成为事实上的XML数据交换格式标准&#xff0c;因为它的易用性和传输效率高。 如果您不了解JSON&#xff0c;那就是Javascript对象表示法&#xff0c;这是一种基于文本的数据交换格式&#xff0c;是名称-值的集合&#xff0c;其中名称严格是字符…

[译文]过犹不及,别再在编程中高射炮打蚊子

原文链接&#xff1a;Anyway,stop recommending bazookas to kill flies in programming. 众成翻译地址&#xff1a;过犹不及&#xff0c;别再在编程中高射炮打蚊子 译者注&#xff1a;翻译这篇吐槽的文章&#xff0c;主要是为了自省~日常工作中确实会犯类似的错误&#xff0…

Java中的for循环

上一章呢我们学习了一下java中的while循环和do while循环 现在我们来了解一下另外一种循环 for循环 for循环是编程语言中一种开界的循环语句&#xff0c;而循环语句 由循环体及循环的终止条件两部分组成&#xff0c;for循环其在各种编程语言中的实现与表达有所出入&#xff0…