在PHP中创建异常有多贵?

时间:2011-07-18 14:21:20

标签: php exception

背景故事:我有一个处理数据库查询的类。问题是查询仅在需要时执行,因此有时可能会远离创建它的位置。现在,如果包装的SQL查询失败,则很难将其追溯到它的原点。

现在的想法是这样的:在创建包装器时,我将创建一个通用的异常对象(它给我回溯和一切)。当在实际执行期间发生某些事情时,预先生成的异常可用于在调试时找到问题的根源。

这不可避免地导致了一个问题:事先生成Exception对象的成本有多高?它甚至是一件聪明的事情吗?你将如何调试延迟的SQL执行?

为了澄清这个过程,这里有一些伪代码:

$list = new QueryWrapper("SELECT ...");

$list->setPage(5);

// Later...
foreach ($list as $entry) { ... }

只有当foreach实际访问$list时才执行查询。

更新:这是一个简约的实现:

public function __construct($query, ... $params = array()) {
        ... 
        $this->createTrace     = new \Exception();
}

// called by the Iterator's rewind()  
private function runQuery() {
    try {
        // execute query;
    }
    catch(\Exception $e) {
        throw new \Exception(
            sprintf(
                'Exception thrown after SQL error (created as %s)',
                $this->createTrace->getTraceAsString()
            ),
            0, $e
        );
    }
}

3 个答案:

答案 0 :(得分:2)

实例化可能在以后抛出的异常听起来像是一个非常不寻常的想法,可能不是我所期望的。我的意思是,正常情况是不抛出异常。所以,大多数情况下你会创建一个可能永远不会被抛出/使用的异常。

在程序流程中稍后抛出的异常会给你堆栈跟踪,所以在我看来:不要打扰也不要那样做。

答案 1 :(得分:0)

在生产环境中,我认为性能“损失”可以忽略不计,因为创建Exception对象与创建任何类相同,这几乎不会受到任何影响。


我不确定这是解决问题的正确方法。这是你期望做的吗?

$list = new QueryWrapper("SELECT ...");
$list->exception = new Exception();

答案 2 :(得分:0)

简单的3v4l测试:

差异似乎很小(在3v4l.org硬件上,每个异常创建大约1-10 us) - 如果每个请求运行几十个查询,则不到一毫秒,即使对于高性能也不太相关网络应用程序)。