当前位置:  开发笔记 > 编程语言 > 正文

php中try-catch的性能

如何解决《php中try-catch的性能》经验,为你挑选了5个好方法。

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

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



1> Steve Jessop..:

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

如果只在故障情况下抛出异常,那么您几乎肯定不关心性能,因为每次执行程序时都不会失败很多次.如果你在一个紧密的循环中失败(也就是说:将你的头撞在砖墙上),你的应用程序可能比缓慢的问题更糟糕.所以不要担心抛出异常的成本,除非你以某种方式被迫将它们用于常规控制流程.

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

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

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


@Marco:它发生在代码中,它不希望*本身使用异常,但却被迫使用API​​.因此,对该API的每次调用最终都会被包装,捕获异常并将其转换为错误代码或其他任何内容.也许这在PHP中并不存在,但是当不同的编码风格发生冲突时,它可能会成为其他语言的危险.另一种情况是,当您希望根据它们的来源(悄悄地记录一些,警告用户其他人,对其他人失败而不是仅仅是异常类型)来处理异常时.那你需要很多尝试.

2> jmucchiello..:

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

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块放入代码中就不会增加大量开销.

3> Brilliand..:

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)."
\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



4> Aeon..:

通常,使用异常来防止意外故障,并在代码中使用错误检查来防止作为正常程序状态一部分的故障.为了显示:

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

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

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



5> Patrick Desj..:

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


介意发布您使用的代码,以便验证它?
循环抛出异常的成本更高,因为它实际上抛出异常.但是如果你只有try-catch块,并且没有抛出任何异常,那么代码不会像@jmucchiello测试那样慢.所以你没有测试try-catch性能,而是处理异常性能,这当然要慢得多.知道它当然很有用,因为在测试之后我知道使用异常来控制应用程序的流程是没有意义的.异常只有在很少见的情况下才有用,并且可以帮助您处理应用程序的错误状态.请参阅Steve Jessop的回答.
如果您还有它,我也希望看到您用于此的代码:-)
推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有