在与Microsoft员工进行代码审查期间,我们在try{}块中遇到了大量代码.她和IT代表建议这可能会影响代码的性能.事实上,他们建议大多数代码应该在try/catch块之外,并且只应该检查重要的部分.微软员工补充说,即将发布的白皮书警告不要使用不正确的try/catch块.
我环顾四周,发现它可以影响优化,但它似乎只适用于范围之间共享变量.
我不是在询问代码的可维护性,甚至不是在处理正确的异常(有问题的代码需要重新分解,毫无疑问).我也没有提到使用流量控制的异常,这在大多数情况下显然是错误的.这些都是重要的问题(有些更重要),但不是重点.
如果不抛出异常,try/catch块如何影响性能?
在Java中,当实际上没有错误时使用throw/catch作为逻辑的一部分通常是一个坏主意(部分)因为抛出和捕获异常是昂贵的,并且在循环中多次执行它通常比其他更慢控制结构,不涉及抛出异常.
我的问题是,抛出/捕获本身或创建Exception对象时产生的成本(因为它获得了很多运行时信息,包括执行堆栈)?
换句话说,如果我这样做
Exception e = new Exception();
Run Code Online (Sandbox Code Playgroud)
但是不要扔它,是投掷的大部分成本,还是投掷+捕获处理成本高昂?
我不是在将代码放入try/catch块中是否会增加执行代码的成本,我问的是,捕获Exception是否是昂贵的部分,或者创建(调用构造函数)Exception是否是昂贵的部分.
另一种问这个问题的方法是,如果我创建了一个Exception实例并且一遍又一遍地抛出它,那么每次抛出时创建一个新的Exception会明快得多吗?
当没有任何异常被抛出时,使用几个try-catch块是"慢"吗?我的问题与此问题相同,但对于Javascript.
假设我有20个函数,其中包含try-catch块.另一个函数调用这20个函数中的每一个.他们都不会抛出异常.由于这个try-catch块,我的代码执行速度会慢还是执行得更差?
javascript performance exception-handling exception try-catch
我听说过你应该避免尝试使用catch块的建议,因为它们很贵.
我的问题是关于.NET平台:为什么尝试块很昂贵?
回复摘要:
在这个问题上显然有两个阵营:那些说试试块是昂贵的,那些说"可能只是一点点".
那些说try块很贵的人通常会提到解除调用堆栈的"高成本".就个人而言,我不相信该辩解-阅读有关的异常处理程序如何存储后,专门在这里.
Jon Skeet坐在"可能只是一点点"的阵营中,写了两篇关于异常和性能的文章,你可以在这里找到.
有一篇文章我觉得非常有趣:它谈到了try块的"其他"性能影响(不一定是内存或cpu消耗).Peter Ritchie提到他发现try块中的代码没有被优化,因为它本来是编译器的.你可以在这里阅读他的发现.
最后,有一篇博客文章介绍了在CLR中实现异常的人的问题.在这里看一下Chris Brumme的文章.
我知道进入一个catch块在执行一个程序时有一些显着的成本,但是,我想知道是否进入try {}块也有任何影响因此我开始在google中寻找一个有很多意见的答案,但没有基准测试所有.我发现的一些答案是:
然而他们并没有用事实回答我的问题,所以我决定自己尝试一下.
这就是我做的.我有一个这种格式的csv文件:
host;ip;number;date;status;email;uid;name;lastname;promo_code;
状态之后的所有内容都是可选的,甚至没有相应的; ,所以在解析验证时必须要查看值是否存在,这就是我想到的try/catch问题.
我在公司里继承的当前代码是这样的:
StringTokenizer st=new StringTokenizer(line,";");
String host = st.nextToken();
String ip = st.nextToken();
String number = st.nextToken();
String date = st.nextToken();
String status = st.nextToken();
String email = "";
try{
email = st.nextToken();
}catch(NoSuchElementException e){
email = "";
}
Run Code Online (Sandbox Code Playgroud)
它重复了用uid,name,lastname和promo_code为电子邮件做的事情.
我改变了一切:
if(st.hasMoreTokens()){
email = st.nextToken();
}
Run Code Online (Sandbox Code Playgroud)
事实上它表现得更快.解析没有可选列的文件时.以下是平均时间:
--- Trying:122 milliseconds
--- Checking:33 milliseconds
Run Code Online (Sandbox Code Playgroud)
然而,这就是让我感到困惑的原因和我要问的原因:当在CSV的所有8000行中运行带有可选列值的示例时,if()版本仍然比try/catch版本表现更好,所以我的问题是
try块是否真的对我的代码没有任何性能影响?
此示例的平均时间为:
--- Trying:105 milliseconds
--- Checking:43 milliseconds
Run Code Online (Sandbox Code Playgroud)
有人能解释一下这里发生了什么吗?
非常感谢
通常我更喜欢空检查.但在目前的情况下,我知道大部分时间我的if条件都会通过,并且很少有合法的场景,其中object可能为null.
此外,负载是巨大的(约500万次电话/小时)
现在我试图从性能角度找出哪种方式更好.已经检查过java中的try/catch vs null检查,但我的情况是唯一的.
还检查哪个更快,在java中尝试catch或if-else(WRT性能)但是这个和上面的都是在通用上下文中,其中通过/失败比率的知识不可用.
public void process(Job job) {
//... some code which processes job
SubJob subJob = job.getSubJob();
if(subJob != null) { // 99% of the time this will pass
//.. do something
}
}
Run Code Online (Sandbox Code Playgroud)
尝试/捕捉版本
public void process(Job job) {
//... some code which processes job
SubJob subJob = job.getSubJob();
try {
//.. do something
}catch(NullPointerException e) { //This may occure only 1% of the time.
//...
}
}
Run Code Online (Sandbox Code Playgroud)
更新:
获胜者是空检查.在Try/catch中,内部JVM将执行空检查并且无论如何都会抛出NPE,并且在JVM中创建异常处理(堆栈等的创建)将是开销.另外,根据另一个答案,现代CPU足够聪明,可以通过良好的预测来处理这些情况,在我的独特案例中,这些预测总是有利于.
我还编写了程序(在我的名字下面发布),结果清楚地表明我的AMD处理器上的空检查更好. …
好多了:
if (condition) {
try {
//something
} catch(SomeEx ex) {}
}
Run Code Online (Sandbox Code Playgroud)
而不是这个:
try {
if (condition) {
//something
}
} catch(SomeEx ex) {}
Run Code Online (Sandbox Code Playgroud)
当我进入try块时,JVM实际上做了什么?
编辑:我不想知道在第二个例子总是进去尝试...请回答问题.
这通常不是关于异常处理的问题,但它特别适用于某些框架的使用.典型起点的几个例子:
public void onFailure(Throwable caught)实现AsyncCallback.public Response toResponse(E throwable)实现ExceptionMapper<E extends Throwable>.上述两种方法都接收一个实例Throwable.通常,我看到开发人员使用一个简单的"if/else if"块来区分处理逻辑:
// As specified by the AsyncCallback class of the GWT framework
public void onFailure(Throwable caught) {
if (caught instanceof AnException) {
// handle AnException
} else if (caught instanceof AnotherException) {
// handle AnotherException
} else if (caught instanceof YetAnotherException) {
// handle YetAnotherException
} else if (caught instanceof ...) {
// and so on...
}
} …Run Code Online (Sandbox Code Playgroud) 问题就是这一切.虽然命中率不是很高(我测量它的速度在1.5x到2x之间),但是try-catch的字节代码与没有try-catch的字节代码之间没有区别.那么是什么让它通常变慢?
PL.请注意,问题不在于抛出异常的开销,而在于进入/离开try块.
编辑:这是代码(在Hotspot 1.6.0_31服务器上运行)
static void tryCatch()
{
int i = 0;
long l1 = getTime();
for(int j = 0; j < 100000; j++)
{
try
{
i++;
}
catch(Exception e)
{
}
}
long l2 = getTime();
System.out.println("with try-catch: " + (l2 - l1) + ": " + i);
}
static void noTryCatch()
{
int i = 0;
long l1 = getTime();
for(int j = 0; j < 100000; j++)
{
i++;
}
long l2 = getTime();
System.out.println("w/o try-catch: …Run Code Online (Sandbox Code Playgroud) 我有一个对象,我想检查此对象或嵌套字段是否为空.我想打印这个neted字段,但我应该检查某个级别是否有null,否则我将获得空指针异常.
我知道我可以这样做:
if( object != null && object.A != null && object.A.B != null && object.A.B.C != null && object.A.B.C.D != null) { doSomething( object.A.B.C.D);}
Run Code Online (Sandbox Code Playgroud)
但它太久了.你知道更好的检查方法吗?
我是Java初学者,并且知道try...catch语句用于处理异常; 表示当try块抛出异常时,catch执行块.所以,我的问题是,当我尝试下面的代码(没有try catch)它抛出一个未报告IOException的read()方法,但当我使用 try catch 它工作正常.
当try块中出现上述异常并exception occured打印时,为什么控件不会转移到catch语句?这是我的代码:
class Test00 {
public static void main(String args[]) {
char ch;
try {
ch=(char)System.in.read();//here exception is thrown without using try..catch
System.out.println(ch);
} catch(Exception e) {
System.out.print("exception occured");
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为编译器会抛出一个异常,这就是代码与try catch一起工作的原因.但是为什么不执行catch块呢?我得错了.
java ×9
performance ×5
try-catch ×5
exception ×3
jvm ×2
.net ×1
benchmarking ×1
c# ×1
coding-style ×1
field ×1
javascript ×1
jvm-hotspot ×1
object ×1
variables ×1