Performance 设计-遇到异常还是避免它?
我有一个简短的设计问题要问大家。我有一个方法,它必须尽可能快地执行,但它也必须提供异常所发生错误的信息Performance 设计-遇到异常还是避免它?,performance,exception,Performance,Exception,我有一个简短的设计问题要问大家。我有一个方法,它必须尽可能快地执行,但它也必须提供异常所发生错误的信息 在一个循环中,函数可能会被调用一千次,但异常很少发生(如果我正确理解了您的问题,您会问:我应该(1)允许异常发生,还是(2)我应该主动测试输入变量(思考:防御驱动) 我的想法 如果可能,您应该尽快检测错误数据 尽可能。调用链中的第一个方法应该处理 这个问题 如果FastMethod方法是朝外的(例如,公共API上的方法),那么我肯定会测试输入参数(例如,number) [项目符号不相关] 不要
在一个循环中,函数可能会被调用一千次,但异常很少发生(如果我正确理解了您的问题,您会问:我应该(1)允许异常发生,还是(2)我应该主动测试输入变量(思考:防御驱动) 我的想法
LibFoo::WiggleBar()
注释中正确指出的那样:参数检查应该放在调用链的最低级别。一般来说,我会以这种方式实现我的代码。谢谢MSalters让我明白过来
我最初的想法是:bullet#1:如果性能确实是一个问题,那么获得时钟周期的一种方法是避免不必要地添加到调用堆栈中
@Tim Krüger:除非你100%确定性能会成为一个问题……我会专注于编写可维护+易于阅读+无bug的代码
更新2
删除了项目符号3。如果我正确理解了你的问题,你会问:我应该(1)允许异常发生,还是(2)我应该主动测试输入变量(思考:防御性驾驶) 我的想法
LibFoo::WiggleBar()
注释中正确指出的那样:参数检查应该放在调用链的最低级别。一般来说,我会以这种方式实现我的代码。谢谢MSalters让我明白过来
我最初的想法是:bullet#1:如果性能确实是一个问题,那么获得时钟周期的一种方法是避免不必要地添加到调用堆栈中
@Tim Krüger:除非你100%确定性能会成为一个问题……我会专注于编写可维护+易于阅读+无bug的代码
更新2
删除了项目符号3。另一个选项是将catch块移动到调用方的一个级别之上,这样就不会在每次迭代中再次设置try/catch块。当然,只有当您不想在异常后继续循环时,它才起作用
一般性能建议:将不完全需要的所有内容移出循环。尽早捕获错误可能会与规则冲突,但这是一个折衷办法。另一个选项是将捕获块移到调用方的一个级别以上,因此不会为每次迭代重新设置try/catch块。cou的作品rse仅当您不想在异常后继续循环时
一般性能建议:将不完全需要的所有内容移出循环。可能与尽早捕获错误的规则冲突,但这是一种折衷。
catch(Exception ex){throw ex;}
是完全无用的代码。无论如何,运行时都是这样做的。如果catch
块除了重试之外什么都不做,它就不应该在那里。因此,您会建议首先进行参数验证吗?我不确定涉及多少个参数验证。为了保持验证的准确性,您可以将验证分组适当地使用|
s和&&
s。另一种方法是传递一个事先经过充分验证的数字,以避免使用FastMethod验证它。@TimKrüger我不推荐任何东西;我只是指出一些死ASCII权重。@michaelb958它比无用更糟糕,会丢失原始堆栈跟踪。catch(异常示例){throw ex;}
是完全无用的代码。无论如何,运行时都是这样做的。如果catch
块除了重试之外什么都不做,它就不应该在那里。因此,您会建议首先进行参数验证吗?我不确定涉及多少个参数验证。为了保持验证的准确性,您可以将验证分组适当地使用|
s和&
s。另一种方法是传递一个事先经过充分验证的数字,以避免快速方法验证。@TimKrüger我不推荐任何东西,我只是指出
int FastMethod(int number)
{
if (number <= 0)
{
throw new ArgumentOutOfRangeException();
}
// (...) more parameter validations
// do some operations with the number here
}
int FastMethod(int number)
{
try
{
// do some operations with the number here
}
catch (Exception ex)
{
throw (ex);
}
}