PHP에서 try-catch의 성능
PHP 5에서 try-catch 문을 사용할 때 어떤 종류의 성능 영향을 고려해야합니까?
이전에 웹에서이 주제에 대해 오래되고 겉보기에 상충되는 정보를 읽었습니다. 내가 현재 작업해야하는 많은 프레임 워크는 php 4에서 만들어졌고 php 5의 좋은 점이 많지 않습니다. 그래서 php에서 try-catchs를 사용하는 경험이 많지 않습니다.
고려해야 할 한 가지는 예외가 발생하지 않는 try 블록의 비용이 실제로 예외를 발생시키고 포착하는 비용과는 다른 질문이라는 것입니다.
예외가 실패한 경우에만 발생하는 경우 프로그램 실행 당 여러 번 실패하지 않기 때문에 성능에 신경 쓰지 않습니다. 빡빡한 루프 (일명 : 벽돌 벽에 머리를 두드리는 것)에서 실패하는 경우 애플리케이션에 느린 것보다 더 나쁜 문제가있을 수 있습니다. 따라서 규칙적인 제어 흐름을 위해 강제로 사용하지 않는 한 예외 발생 비용에 대해 걱정하지 마십시오.
누군가 예외를 발생시키는 프로파일 링 코드에 대해 이야기하는 답변을 게시했습니다. 직접 테스트 한 적은 없지만, 아무 것도 던지지 않고 try 블록을 들어오고 나가는 것보다 훨씬 더 큰 성능 저하를 보일 것이라고 확신합니다.
고려해야 할 또 다른 사항은 많은 수준의 호출을 중첩하는 경우 반환 값을 확인하고 모든 호출에서 오류를 전파하는 것보다 맨 위에 하나의 try ... catch를 사용하는 것이 더 빠를 수 있다는 것입니다.
모든 호출을 자체 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) {}
}
내 WinXP 상자에서 1000000이 실행되면 아파치와 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
Generally, use an exception to guard against unexpected failures, and use error checking in your code against failures that are part of normal program state. To illustrate:
Record not found in database - valid state, you should be checking the query results and messaging the user appropriately.
SQL error when trying to fetch record - unexpected failure, the record may or may not be there, but you have a program error - this is good place for an exception - log error in error log, email the administrator the stack trace, and display a polite error message to the user advising him that something went wrong and you're working on it.
Exceptions are expensive, but unless you handle your whole program flow using them, any performance difference should not be human-noticeable.
I have not found anything on Try/Catch performance on Google but a simple test with a loop throwing error instead of a IF statement produce 329ms vs 6ms in a loop of 5000.
Sorry to post to a very old message, but I read the comments and I somewhat disagree, the difference might be minimal with simple piece of codes, or it could be neglectable where the Try/Catch are used for specific parts of code that are not always predictable, but I also believe (not tested) that a simple:
if(isset($var) && is_array($var)){
foreach($var as $k=>$v){
$var[$k] = $v+1;
}
}
is faster than
try{
foreach($var as $k=>$v){
$var[$k] = $v+1;
}
}catch(Exception($e)){
}
I also believe (not tested) that a:
<?php
//beginning code
try{
//some more code
foreach($var as $k=>$v){
$var[$k] = $v+1;
}
//more code
}catch(Exception($e)){
}
//output everything
?>
is more expensive than have extra IFs in the code
Thats a very good question!
I have tested it many times and never saw any performance issue ;-) It was true 10 years ago in C++ but I think today they have improved it a lot since its so usefull and cleaner.
But I am still afraid to surround my first entry point with it:
try {Controller::run();}catch(...)
I didnt test with plenty of functions call and big include .... Is anyone has fully test it already?
Generally speaking, they're expensive and not worthwhile in PHP.
Since it is a checked expressions language, you MUST catch anything that throws an exception.
When dealing with legacy code that doesn't throw, and new code that does, it only leads to confusion.
Good luck!
참고URL : https://stackoverflow.com/questions/104329/performance-of-try-catch-in-php
'Program Tip' 카테고리의 다른 글
여러 표현식에서 ng-click을 사용하는 방법은 무엇입니까? (0) | 2020.12.10 |
---|---|
Intent.VIEW_ACTION이있는 Android 설치 APK가 파일 공급자와 작동하지 않음 (0) | 2020.12.10 |
사용자 정의 유형으로 std :: set, 중복이 없는지 확인하는 방법 (0) | 2020.12.10 |
헤더 파일의 변수 선언 (0) | 2020.12.10 |
파이썬 함수에서 데코레이터를 제거하는 방법 (0) | 2020.12.10 |