Intereting Posts
PHP Отправка электронной почты BCC PHP переупорядочивает массив имен месяцев Могу ли я перебирать две петли равного размера с помощью foreach? PHP debug_backtrace в производственном коде для получения информации о методе вызова? Эмуляция названных параметров функции в PHP, хорошая или плохая идея? В структуре Yii, как я могу объединить столбцы и показать в качестве отображаемой строки в выпадающем списке Laravel 5 charset не работает правильно на представлениях. Но он работает хорошо, когда я сбрасываю его с контроллера Как шифровать / расшифровывать AES с помощью Libsodium-PHP Как проверить вложенные поля в Zend Framework 2 без использования фабрики Codeignitor- как загрузить новую страницу после удаления index.php Как отключить регистрацию нового пользователя в Laravel 5 Защита Magento CSRF CakePHP3 пользовательский метод поиска, содержащий и не работает при попытке отобразить связанное поле модели Видимость атрибутов модели Laravel / Eloquent Model PHP Анонимный объект – целочисленные свойства

Производительность try-catch в php

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

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

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

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

Кто-то отправил ответ, говорящий о профилировании кода, который выдает исключение. Я никогда не тестировал его сам, но я уверенно предсказываю, что это будет показывать гораздо больший успех, чем просто входить и выходить из блока 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) {} } 

С 1000000 запусков в моем окне WinXP запустите 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 при попытке получить запись – неожиданный сбой, запись может быть или не быть, но у вас есть программная ошибка – это хорошее место для ошибки журнала ошибок в журнале ошибок, отправки администратору трассировки стека и отображения вежливое сообщение об ошибке, сообщающее пользователю, что что-то пошло не так, и вы работаете над этим.

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

Я ничего не нашел в работе Try / Catch в Google, но простой тест с ошибкой металирования цикла вместо утверждения IF выражает 329ms против 6ms в петле 5000.

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

является более дорогим, чем дополнительные IF в коде

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

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

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

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

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

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

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

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

Удачи!