在php 5中使用try-catch语句时需要考虑哪些性能影响?

我之前在网上看过一些关于这个主题的旧的,看似相互矛盾的信息。我目前必须使用的很多框架都是在php 4上创建的,缺少php 5的许多细节。所以,我自己在使用php的try-catchs方面没有多少经验。

有帮助吗?

解决方案

要考虑的一件事是,没有抛出异常的try块的成本与实际抛出和捕获异常的成本是一个不同的问题。

如果仅在失败的情况下抛出异常,您几乎肯定不关心性能,因为每次执行程序时都不会失败很多次。如果你在一个紧凑的循环中失败了(a.k.a:将你的头撞在砖墙上),你的应用程序可能比慢速更糟糕。所以不要担心抛出异常的代价,除非你不得不将它们用于常规控制流程。

有人发表了一个答案,谈论分析引发异常的代码。我自己从来没有对它进行过测试,但我自信地预测,这将显示出更大的性能,而不仅仅是进入和退出try块而不会抛出任何东西。

要考虑的另一件事是,在嵌套调用很多级别的情况下,在顶部进行单次尝试...捕获甚至可以更快地检查返回值并在每次调用时传播错误

与那种情况相反,你发现你在自己的try ... catch块中包含每个调用,你的代码会变慢。而且丑陋。

其他提示

我很无聊并且描述了以下内容(我将时间码留下了):

function no_except($a, $b) { 
    $a += $b;
    return $a;
}
function except($a, $b) { 
    try {
        $a += $b;
    } catch (Exception $e) {}
    return $a;
}

使用两个不同的循环:

echo 'no except with no surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
    no_except(5, 7);
}
echo 'no except with surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
    try {
        no_except(5, 7);
    } catch (Exception $e) {}
}
echo 'except with no surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
    except(5, 7);
}
echo 'except with surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
    try {
        except(5, 7);
    } catch (Exception $e) {}
}

在我的WinXP框上运行1000000运行apache和PHP 5.2.6:

no except with no surrounding try = 3.3296
no except with surrounding try = 3.4246
except with no surrounding try = 3.2548
except with surrounding try = 3.2913

这些结果是一致的,无论测试顺序如何,都保持相似的比例。

结论:添加处理罕见异常的代码并不比忽略异常的代码慢。

Try-catch块不是性能问题 - 真正的性能瓶颈来自创建异常对象。

测试代码:

function shuffle_assoc($array) { 
    $keys = array_keys($array);
    shuffle($keys);
    return array_merge(array_flip($keys), $array);
}

$c_e = new Exception('n');

function no_try($a, $b) { 
    $a = new stdclass;
    return $a;
}
function no_except($a, $b) { 
    try {
        $a = new Exception('k');
    } catch (Exception $e) {
        return $a + $b;
    }
    return $a;
}
function except($a, $b) { 
    try {
        throw new Exception('k');
    } catch (Exception $e) {
        return $a + $b;
    }
    return $a;
}
function constant_except($a, $b) {
    global $c_e;
    try {
        throw $c_e;
    } catch (Exception $e) {
        return $a + $b;
    }
    return $a;
}

$tests = array(
    'no try with no surrounding try'=>function() {
        no_try(5, 7);
    },
    'no try with surrounding try'=>function() {
        try {
            no_try(5, 7);
        } catch (Exception $e) {}
    },
    'no except with no surrounding try'=>function() {
        no_except(5, 7);
    },
    'no except with surrounding try'=>function() {
        try {
            no_except(5, 7);
        } catch (Exception $e) {}
    },
    'except with no surrounding try'=>function() {
        except(5, 7);
    },
    'except with surrounding try'=>function() {
        try {
            except(5, 7);
        } catch (Exception $e) {}
    },
    'constant except with no surrounding try'=>function() {
        constant_except(5, 7);
    },
    'constant except with surrounding try'=>function() {
        try {
            constant_except(5, 7);
        } catch (Exception $e) {}
    },
);
$tests = shuffle_assoc($tests);

foreach($tests as $k=>$f) {
    echo $k;
    $start = microtime(true);
    for ($i = 0; $i < 1000000; ++$i) {
        $f();
    }
    echo ' = '.number_format((microtime(true) - $start), 4)."<br>\n";
}

结果:

no try with no surrounding try = 0.5130
no try with surrounding try = 0.5665
no except with no surrounding try = 3.6469
no except with surrounding try = 3.6979
except with no surrounding try = 3.8729
except with surrounding try = 3.8978
constant except with no surrounding try = 0.5741
constant except with surrounding try = 0.6234

通常,使用异常来防止意外故障,并在代码中使用错误检查来防止作为正常程序状态一部分的故障。举例说明:

  1. 在数据库中找不到记录 - 有效状态,您应该检查查询结果并正确地向用户发送消息。

  2. 尝试获取记录时出现SQL错误 - 意外失败,记录可能存在也可能不存在,但是您有程序错误 - 这是异常的好地方 - 错误日志中的日志错误,通过电子邮件发送给管理员堆栈跟踪,并向用户显示礼貌的错误消息,告知他出现了问题并且您正在处理它。

  3. 例外是昂贵的,但除非你使用它们处理整个程序流程,否则任何性能差异都不应该是人类明显的。

我在Google上没有找到关于Try / Catch性能的任何内容,但是使用循环抛出错误而不是IF语句的简单测试在5000循环中产生329ms vs 6ms。

很抱歉发布一条非常旧的消息,但是我读了评论,我有些不同意,简单的代码区别可能很小,或者在Try / Catch用于代码的特定部分时可能会忽略不计这并不总是可预测的,但我也相信(未经测试)这是一个简单的:

if(isset($var) && is_array($var)){
    foreach($var as $k=>$v){
         $var[$k] = $v+1;
    }
}

try{
    foreach($var as $k=>$v){
        $var[$k] = $v+1;
    }
}catch(Exception($e)){
}

我也相信(未经测试)a:

<?php
//beginning code
try{
    //some more code
    foreach($var as $k=>$v){
        $var[$k] = $v+1;
    }
    //more code
}catch(Exception($e)){
}
//output everything
?>

比代码中的额外IF更昂贵

这是一个非常好的问题!

我已经测试了很多次,从未看到任何性能问题;-) 10年前在C ++中确实如此,但我认为今天它们已经改进了很多,因为它非常有用和清洁。

但我仍然害怕用它来包围我的第一个切入点:

try {Controller::run();}catch(...)

我没有测试大量的函数调用和大包含....是否有人已经完全测试了它?

一般来说,它们很贵,而且在PHP中也不值得。

由于它是一种经过检查的表达式语言,因此必须捕获任何引发异常的内容。

在处理不抛出的遗留代码和新代码时,只会导致混淆。

祝你好运!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top