Pergunta

Que tipo de implicações de desempenho estão lá para considerar quando usando instruções try-catch em php 5?

Eu li algumas informações antigas e aparentemente conflitantes sobre este assunto na web antes. Uma grande parte do quadro Eu agora tenho de trabalhar com foi criado em php 4 e não tem muitas das sutilezas de php 5. Então, eu não tenho muita experiência me em usar try-catchs com php.

Foi útil?

Solução

Uma coisa a considerar é que o custo de um bloco try onde nenhuma exceção é lançada é uma questão diferente do custo de realmente jogar e pegar uma exceção.

Se exceções só são jogados em casos de falha, você quase certamente não se preocupam com o desempenho, já que você não vai falhar muitas vezes por execução de seu programa. Se você está falhando em um loop (a.k.a: bater a cabeça contra uma parede de tijolos), seu aplicativo provavelmente tem problemas piores do que ser lento. Então não se preocupe com o custo de lançar uma exceção, a menos que você está de alguma forma forçados a usá-los para controle de fluxo regular.

Alguém postou uma resposta falando sobre perfis do código que gera uma exceção. Eu nunca testei por mim mesmo, mas eu confiantemente prever que esta irá mostrar um acerto de desempenho muito maior do que apenas ir dentro e fora de um bloco try sem jogar nada.

Outra coisa a considerar é que onde ninho chama um monte de níveis de profundidade, ele pode até mesmo ser mais rápido para ter um único try ... catch bem no topo do que é para verificar valores de retorno e erros propagar em cada chamada .

No oposto dessa situação, onde você achar que você está envolvendo todas as chamadas em seu próprio bloco try ... catch, seu código será mais lento. E mais feia.

Outras dicas

Eu estava entediado e perfilados o seguinte (eu deixei o código de tempo limite):

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

usando dois loops diferentes:

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) {}
}

Com 1000000 corre no meu WinXP caixa de executar o Apache e 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

Estes resultados foram consistentes e manteve-se em proporção similar não importa qual ordem dos testes executados.

Conclusão:. Adicionando código para lidar com raras exceções não mais lento é que o código as exceções ignora

blocos try-catch não é um problema de desempenho -. O gargalo de desempenho real vem desde a criação de objetos de exceção

código de teste:

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";
}

Resultado:

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

Geralmente, usar uma exceção para proteger contra falhas inesperadas, e uso a verificação de erros em seu código contra falhas que fazem parte do estado do programa normal. Para ilustrar:

  1. Record não encontrado na base de dados - estado válido, você deve verificar os resultados da consulta e mensagens que o usuário adequadamente

  2. .
  3. Erro SQL ao tentar buscar recorde - falha inesperada, o registro pode ou não estar lá, mas você tem um erro de programa - este é um bom lugar para uma exceção - Erro de log no log de erro, enviar e-mail ao administrador o rastreamento de pilha, e exibir uma mensagem de erro educado para o usuário avisando-o de que algo deu errado e você está trabalhando nisso.

As excepções são caros, mas a menos que você lidar com o seu fluxo de programa inteiro usá-los, qualquer diferença de desempenho não deve ser homem-perceptível.

Eu não encontrei nada sobre o desempenho try / catch no Google, mas um teste simples com um erro de loop jogando em vez de uma instrução IF produzir 329ms vs 6ms em um loop de 5000.

Desculpe post para uma mensagem muito velha, mas eu li os comentários e eu um pouco discordar, a diferença pode ser mínima com simples pedaço de códigos, ou poderia ser negligenciável onde o try / catch são utilizados para partes específicas do código que nem sempre são previsíveis, mas também acredito (não testado) que um simples:

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

é mais rápido do que

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

Eu também acredito (não testado) que a:

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

é mais caro do que ter FI extras no código

Isso é uma pergunta muito boa! ??

Eu testei-o muitas vezes e nunca viu qualquer problema de desempenho ;-) Era verdade 10 anos atrás, em C ++, mas eu acho que hoje eles melhoraram-lo muito desde a sua útil assim e mais limpo.

Mas eu ainda tenho medo de cercar o meu primeiro ponto de entrada com ele:

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

I teste não funcionavam com abundância de funções de ligar e grande incluem .... Tem alguém tem testá-lo totalmente já?

De modo geral, eles são caros e não vale a pena em PHP.

Uma vez que é uma linguagem de expressões marcada, você deve pegar qualquer coisa que lança uma exceção.

Ao lidar com código legado que não joga, e novo código que faz, ele só leva à confusão.

Boa sorte!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top