【问题标题】:try catch for performance c#尝试捕捉性能 c#
【发布时间】:2017-02-10 17:37:03
【问题描述】:

我对 try catch 的了解有限。但我想知道它是否可以用来获得性能。

例如,我正在创建这个体素引擎,其中一个函数是这样的:

Block GetBlockInChunk(Vector Position){
    if(InBound(Position)){
        return Database.GetBlock();
    }
    return null;
}

这里它必须检查给定位置的边界,使用try catch,然后你可以删除它们?

Block GetBlockInChunk(Vector Position){
    try{
        return Database.GetBlock();
    }
    catch{
        return null;
    }
}

我觉得这可能是一种糟糕的做法,但我很好奇。

【问题讨论】:

  • try..catch 引入了开销并且不会提高 AFAIK 的性能。
  • 也适用于异常情况,默认情况下不使用。在这里检查边界似乎比让它抛出异常更好的方法。
  • 啊好吧,有道理。 :)
  • 你应该避免异常。只在你没有预料到的地方使用异常。 try 不慢,catch 是。

标签: c# performance try-catch


【解决方案1】:

我在上述评论中提供的链接描述了为什么当 if 语句会阻止抛出异常时不应该使用 try-catch,但为了显示实际性能数字,我编写了这个快速的小测试程序。

Stopwatch watch = new Stopwatch();

int[] testArray = new int[] { 1, 2, 3, 4, 5 };
int? test = null;

watch.Start();
for (int i = 0; i < 10000; i++)
{
    try
    {
        testArray[(int)test] = 0;
    }
    catch { }
}
watch.Stop();

Console.WriteLine("try-catch result:");
Console.WriteLine(watch.Elapsed);
Console.WriteLine();

watch.Restart();
for (int i = 0; i < 10000; i++)
{
    if (test != null)
        testArray[(int)test] = 0;
}
watch.Stop();

Console.WriteLine("if-statement result:");
Console.WriteLine(watch.Elapsed);

程序的结果是这样的:

try-catch result:
00:00:32.6764911

if-statement result:
00:00:00.0001047

如您所见,try-catch 方法在捕获异常时会引入大量开销,需要 30 多秒才能在我的机器上完成 10,000 个周期。另一方面,if 语句运行得如此之快,以至于它基本上是瞬时的。与 try-catch 相比,性能提升了近 3,000,000%。

(这不是一个严格的基准测试,有很多方法可以编写和运行它以获得更精确的数字,但这应该让您很好地了解使用 if-尽可能在 try-catch 上声明。)

【讨论】:

  • 堆栈跟踪(当抛出异常时)是非常耗时的操作(与简单的 if 相比)
  • 优秀的答案! 3,000,000% 太疯狂了!哈哈
【解决方案2】:

大约 2 年后,但它仍然相关......

我尊重其他回复,但我认为这里有一个基本的误解,目的是为了 try-catch。 Try Catch 是 C# 和 dotnet 中一种非常有效的方法,用于识别开发和代码生命周期中的错误。它从来没有打算成为一个使用不同的工具,如果它被火了,那就意味着你有一个需要修复的错误。

它要解决的问题是停止代码的标准错误消息,然后您需要深入挖掘。通过try and catch您可以知道问题发生在哪种方法中并缩小搜索范围。

作为标准,我使用 try-catch 包装我的所有方法,并添加了一个附加功能,该功能将错误消息与方法名称和其他基本信息(如时间)以及一些有用的数据锚点写入调试文件,即使代码在生产中,我也可以访问。这是无价的!​​p>

就性能而言,如果 try-catch 没有触发(这应该是正常的),则不会降低性能,因为它只是一个简单的变形器。如果有人真的很喜欢高水平的性能并且每个分数都很重要,那么可以使用预编译器条件(#if...)来消除它。

希望这有帮助。

【讨论】:

  • 对不起,这并不一定意味着存在“错误”。例如,当写入文件并且磁盘空间耗尽时,可能会发生异常。这是“异常”,需要处理,但不是代码中的错误。
  • 这个答案让我想起了二十年前我在第一份工作中作为初级开发人员所做的事情。出于完全相同的原因,我还将每个方法都包装在(当时的 VB6)等效的 try-catch 中 - 想要调试错误。我在这个答案中找不到任何真实、有用或良好做法的东西,因此投反对票。
  • @bboyle1234 公平地说,有一些有用的信息是:As far as performance, if the try-catch doesn't fire (which should be normal), there is no performance reduction,我花了一段时间才理解。只有在生成堆栈跟踪时才会发生性能损失。 @Shai Try ... Catching 每个方法都不是必需的,因为堆栈跟踪已经包含您正在寻找的信息。
  • @Ama,我在使用 .net 基准测试之前已经对其进行了测试,发现即使没有引发异常,也会发生性能损失。也许我错了 - 是否有关于它的文档?我喜欢你的公平感:)
  • 我没有找到任何官方文档,但这里有一个完整的争论:stackoverflow.com/questions/1308432/…。简而言之,看起来只有 JIT 优化在某些情况下可能会受到 Try Catch 块的影响,而且这些优化通常很小。
猜你喜欢
  • 2010-11-23
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
  • 1970-01-01
相关资源
最近更新 更多