2008-09-19 3 views
49

Какое влияние на производительность возникает при использовании утверждений try-catch в php 5?Производительность try-catch в php

Я читал ранее старую и, казалось бы, противоречивую информацию по этому вопросу в Интернете. Большая часть структуры, с которой я в настоящее время работаю, была создана на php 4 и не имеет многих тонкостей php 5. Итак, у меня нет большого опыта использования try-catch с php.

ответ

60

Одна вещь, которую следует учитывать, заключается в том, что стоимость блока try, где не генерируется исключение, - это другой вопрос из стоимости фактического броска и исключения исключения.

Если исключения случаются только в случаях сбоя, вы почти наверняка не заботитесь о производительности, поскольку вы не будете терпеть неудачу очень много раз за выполнение вашей программы. Если вы терпите неудачу в петле (a.k.a: стучите головой о кирпичную стену), ваше приложение, вероятно, имеет более серьезные проблемы, чем медленное. Поэтому не беспокойтесь о стоимости выброса исключения, если вы каким-то образом не вынуждены использовать их для регулярного потока управления.

Кто-то отправил ответ, говорящий о профилировании кода, который выдает исключение. Я никогда не тестировал его сам, но я уверенно предсказываю, что это будет показывать гораздо больший успех, чем просто входить и выходить из блока try, не бросая ничего.

Еще одна вещь, которую следует учитывать, заключается в том, что там, где вы гнездо называет много уровней, может быть даже быстрее иметь одну попытку ... поймать справа вверху, чем проверять возвращаемые значения и распространять ошибки на каждом вызов.

В противоположность этой ситуации, когда вы обнаружите, что вы завершаете каждый звонок в своем собственном try ... catch block, ваш код будет медленнее. И уродливее.

+0

Я никогда не видел код, где они обертывают каждый вызов с помощью `try catch` вместо использования одного большого` try cacth` для обертывания всех вызовов! – 2011-04-06 11:56:28

-8

Вообще говоря, они дороги и не стоят в PHP.

Поскольку это проверенный язык выражений, вы ДОЛЖНЫ уловить все, что выдает исключение.

При работе с устаревшим кодом, который не выбрасывает, и новым кодом, который делает, это только приводит к путанице.

Удачи вам!

+2

Для записи, PHP не имеет "проверяемые исключения". Все исключения работают как «RuntimeException» Java. – RJHunter 2009-07-21 00:35:09

5

Я не нашел ничего на производительности Try/Выгоды на Google, но простой тест с петлей метания ошибки вместо а, если заявление производит 329ms против 6 мса в петле 5000.

+7

Разум, отправляющий код, который вы использовали, чтобы его можно было проверить? – UnkwnTech 2008-09-19 18:37:01

+2

Я тоже хотел бы увидеть код, который вы использовали для этого, если у вас его все еще есть :-) – 2011-04-22 22:21:11

+0

@Patrick Desjardins: не могли бы вы опубликовать код для теста или дать нам ссылку на него. – 2012-12-29 17:59:59

8

Как правило, использовать исключение защищать от непредвиденных сбоев и использовать проверку ошибок в вашем коде против сбоев, которые являются частью нормального состояния программы. Для иллюстрации:

  1. Запись не найдена в базе данных - действительное состояние, вы должны проверять результаты запроса и сообщать пользователю надлежащим образом.

  2. Ошибка SQL при попытке получить запись - неожиданный сбой, запись может быть или не быть, но у вас есть программная ошибка - это хорошее место для исключения - ошибка журнала в журнале ошибок, электронная почта администратора трассировать трассировку стека и отображать вежливое сообщение об ошибке, сообщающее пользователю, что что-то пошло не так, и вы работаете над этим.

Исключения стоят дорого, но если вы не будете обрабатывать весь ваш поток программ, используя их, любая разница в производительности не должна быть заметна человеком.

45

мне было скучно, и профилированные следующее (я оставил код таймаут):

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

С 1000000 работает на моем WinXP окно запуска апача и 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 

Эти результаты были согласованными и оставались в одинаковой пропорции независимо от того, чтобы заказ прошел.

Заключение: добавление кода для обработки редких исключений не медленнее, чем код игнорирует исключения.

1

Это очень хороший вопрос!

Я тестировал его много раз и никогда не видел проблемы с производительностью ;-) Это было верно 10 лет назад на C++, но я думаю, что сегодня они значительно улучшили его с момента его использования и очистки.

Но я до сих пор боюсь, чтобы окружить свою первую точку входа с ним:

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

я не сделал тест с большим количеством вызова функций и большой включать в себя .... Кто-нибудь полностью протестировать его уже?

2

Извините, что публиковать сообщения в очень старом сообщении, но я читаю комментарии, и я несколько не согласен с тем, что разница может быть минимальной с простой частью кода или может быть пренебрежимой, если 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)){ 
} 

Я также считаю (не проверено), что:

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

дороже, чем дополнительный МСФ в коде

14

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 
Смежные вопросы