C #에서 try / catch의 실제 오버 헤드는 무엇입니까?


94

그래서 저는 try / catch가 약간의 오버 헤드를 추가하므로 프로세스 흐름을 제어하는 ​​좋은 방법이 아니라는 것을 알고 있습니다.하지만이 오버 헤드는 어디에서 왔으며 실제 영향은 무엇입니까?

답변:


52

나는 언어 구현의 전문가는 아니지만 (그러니 이것을 염두에 두십시오), 가장 큰 비용 중 하나는 스택을 풀고 스택 추적을 위해 저장하는 것이라고 생각합니다. 나는 이것이 예외가 던져 질 때만 발생한다고 생각합니다 (하지만 나는 모릅니다), 그렇다면 예외가 던져 질 때마다 이것은 적절한 크기의 숨겨진 비용이 될 것입니다. 다른 코드에서는 많은 일이 진행되고 있습니다.

예외적 인 동작에 대한 예외를 사용하는 한 문제가되지 않는다고 생각합니다 (프로그램을 통한 일반적인 예상 경로가 아님).


33
더 정확하게는 시도가 저렴하고 캐치가 저렴하며 던지기가 비쌉니다. 시도하고 잡는 것을 피하면 던지기는 여전히 비쌉니다.
Windows 프로그래머

4
흠-주석에서 마크 업이 작동하지 않습니다. 다시 시도하려면-예외는 "예외 동작"또는 조건이 아닌 오류에 대한 것입니다. blogs.msdn.com/kcwalina/archive/2008/07/17/…
HTTP 410

2
@Windows 프로그래머 통계 / 소스 부탁드립니다.
KAPE

100

여기서 확인해야 할 세 가지 사항 :

  • 첫째, 실제로 코드에서 try-catch 블록을 사용하는 경우 성능 저하가 거의 또는 전혀 없습니다. 응용 프로그램에 포함하지 않으려 고 할 때 고려해서는 안됩니다. 성능 저하는 예외가 발생할 때만 작용합니다.

  • 다른 사람들이 언급 한 스택 해제 작업 등에 추가로 예외가 발생하면 스택 추적과 같은 예외 클래스의 구성원을 채우기 위해 런타임 / 반사 관련 작업이 많이 발생한다는 사실을 알아야합니다. 객체 및 다양한 유형 멤버 등

  • 나는 이것이 throw;예외를 다시 던질 경우 일반적인 조언 이 예외를 다시 던지거나 새로운 것을 생성하는 것보다 단순한 경우에 모든 스택 정보가 다시 수집되는 이유 중 하나라고 생각합니다. 던지는 것은 모두 보존됩니다.


41
또한 : "throw ex"로 예외를 다시 발생하면 원래 스택 추적이 손실되고 CURRENT 스택 추적으로 대체됩니다. 드물게 원하는 것. "throw"만하면 Exception의 원래 스택 추적이 유지됩니다.
Eddie

@Eddie 또는throw new Exception("Wrapping layer’s error", ex);
binki

21

예외가 발생하지 않을 때 try / catch / finally를 사용하는 오버 헤드 또는 프로세스 흐름을 제어하기 위해 예외를 사용하는 오버 헤드에 대해 질문하고 있습니까? 후자는 다이너마이트 막대를 사용하여 유아의 생일 촛불을 밝히는 것과 다소 유사하며 관련 오버 헤드는 다음 영역에 속합니다.

  • 일반적으로 캐시에 있지 않은 상주 데이터에 액세스하는 예외로 인해 추가 캐시 누락을 예상 할 수 있습니다.
  • 일반적으로 애플리케이션의 작업 세트에없는 비상주 코드 및 데이터에 액세스하는 예외로 인해 추가 페이지 오류가 발생할 수 있습니다.

    • 예를 들어 예외를 throw하려면 CLR이 현재 IP 및 모든 프레임의 반환 IP를 기반으로 finally 및 catch 블록의 위치를 ​​찾아야하며 예외가 처리 될 때까지 필터 블록을 추가해야합니다.
    • 메타 데이터 읽기 등 진단 목적으로 프레임을 생성하기위한 추가 건설 비용 및 이름 확인
    • 위의 두 항목 모두 일반적으로 "콜드"코드와 데이터에 액세스하므로 메모리 부족이 발생하면 하드 페이지 오류가 발생할 수 있습니다.

      • CLR은 지역성을 개선하기 위해 자주 사용되는 데이터와는 거리가 멀어 자주 사용되는 코드와 데이터를 넣으려고하므로 추위를 더워지게하므로 불리하게 작용합니다.
      • 하드 페이지 폴트의 비용은 다른 모든 것을 무시할 것입니다.
  • 일반적인 캐치 상황은 종종 깊기 때문에 위의 효과가 확대되는 경향이 있습니다 (페이지 폴트 가능성 증가).

비용의 실제 영향은 당시 코드에서 진행중인 다른 작업에 따라 크게 달라질 수 있습니다. Jon Skeet는 유용한 링크와 함께 여기에 좋은 요약을 제공 합니다. 나는 예외로 인해 성능이 크게 저하되는 지점에 도달하면 성능뿐만 아니라 예외를 사용하는 데 문제가 있다는 그의 진술에 동의하는 경향이 있습니다.


6

내 경험상 가장 큰 오버 헤드는 실제로 예외를 던지고 처리하는 것입니다. 나는 누군가가 어떤 객체를 편집 할 권한이 있는지 확인하기 위해 다음과 유사한 코드를 사용하는 프로젝트에서 일한 적이 있습니다. 이 HasRight () 메서드는 프레젠테이션 레이어의 모든 곳에서 사용되었으며 종종 수백 개의 개체에 대해 호출되었습니다.

bool HasRight(string rightName, DomainObject obj) {
  try {
    CheckRight(rightName, obj);
    return true;
  }
  catch (Exception ex) {
    return false;
  }
}

void CheckRight(string rightName, DomainObject obj) {
  if (!_user.Rights.Contains(rightName))
    throw new Exception();
}

테스트 데이터베이스가 테스트 데이터로 가득 차면 새 양식을 여는 동안 매우 눈에 띄는 속도 저하가 발생합니다.

그래서 나는 그것을 다음과 같이 리팩토링했는데, 나중에 빠른 측정에 따르면 약 2 배 더 빠릅니다.

bool HasRight(string rightName, DomainObject obj) {
  return _user.Rights.Contains(rightName);
}

void CheckRight(string rightName, DomainObject obj) {
  if (!HasRight(rightName, obj))
    throw new Exception();
}

즉, 정상적인 프로세스 흐름에서 예외를 사용하는 것은 예외없이 유사한 프로세스 흐름을 사용하는 것보다 약 2 배 더 느립니다.


1
여기서 예외를 던지는 이유는 무엇입니까? 그 자리에서 권리가없는 경우를 처리 할 수 ​​있습니다.
ThunderGr 2013 년

@ThunderGr 그게 실제로 제가 변경 한 것입니다.
Tobi

5

일반적으로 받아 들여지는 이론과는 달리 try/ catch는 성능에 상당한 영향을 미칠 수 있으며 예외가 발생하는지 여부입니다!

  1. 일부 자동 최적화를 비활성화하고 (설계 상) 일부 경우 디버깅 지원 에서 예상 할 수있는 디버깅 코드를 삽입 합니다. 이 점에서 항상 저와 동의하지 않는 사람들이있을 것이지만, 언어는 그것을 필요로하고 분해는 그것을 보여 주므로 사전 정의에 따라 망상 적 입니다.
  2. 유지 관리에 부정적인 영향을 미칠 수 있습니다. 이것은 실제로 여기에서 가장 중요한 문제이지만 (거의 전적으로 그것에 초점을 맞춘) 마지막 답변이 삭제되었으므로 더 중요한 문제가 아닌 덜 중요한 문제 (마이크로 최적화)에 초점을 맞추려고 노력할 것입니다 ( 거시적 최적화).

전자는 지난 몇 년 동안 마이크로 소프트의 MVP로 블로그 게시물의 몇 가지에 덮여, 그리고 당신이 쉽게 찾을 수있는 신뢰 아직 StackOverflow의이 걱정되어 훨씬 에 대한 내용 나는대로 그들 중 일부에 대한 링크를 제공 할 수 있습니다 있도록 필러 증거 :

  • try/ catch/finally ( 및 파트 2 ) 의 성능 영향 , Peter Ritchie가try/catch/finally비활성화하는 최적화를 탐색합니다 (표준의 인용문을 사용하여 더 자세히 설명하겠습니다).
  • 성능 프로파일 링 ParseTryParseConvertTo 이안 허프으로는 "예외 처리가 매우 느립니다"과 내공으로이 점을 보여줍니다 있음을 노골적으로 주장Int.Parse하고Int.TryParse주장하는 사람이 서로 ...에 대하여 그TryParse용도가try/catch무대 뒤에서,이 되거한다고!

/ 사용 여부와 상관없이 분해 된 코드의 차이점을 보여주는 이 답변 도 있습니다 .trycatch

코드 생성에서 노골적으로 관찰 할 수있는 오버 헤드 가 있다는 것이 너무 분명해 보이며 , 그 오버 헤드는 마이크로 소프트가 중요하게 여기는 사람들이 인정하는 것 같습니다! 그러나 나는 인터넷을 반복하고 있습니다 ...

예, 한 줄의 간단한 코드에 대해 수십 개의 추가 MSIL 명령이 있으며 비활성화 된 최적화도 다루지 않으므로 기술적으로는 마이크로 최적화입니다.


프로그래머의 생산성 (매크로 최적화)에 초점을 맞춰 삭제 된 답변을 몇 년 전에 게시했습니다.

여기저기서 CPU 시간의 몇 나노초를 절약하지 않아도 인간이 수동으로 최적화하는 데 많은 시간이 누적 된 것을 보충 할 수 있기 때문에 이는 불행한 일입니다. 상사가 더 많은 비용을 지불하는 것은 무엇입니까? 한 시간 중 한 시간입니까, 아니면 컴퓨터가 실행중인 한 시간입니까? 어떤 시점에서 우리는 플러그를 뽑고 더 빠른 컴퓨터를 구입할 때임을 인정 합니까?

분명히 우리는 코드뿐만 아니라 우선 순위를 최적화 해야합니다 ! 마지막 답변에서 두 코드 스 니펫의 차이점을 그렸습니다.

try/ 사용 catch:

int x;
try {
    x = int.Parse("1234");
}
catch {
    return;
}
// some more code here...

try/ 사용하지 않음 catch:

int x;
if (int.TryParse("1234", out x) == false) {
    return;
}
// some more code here

프로파일 링 / 최적화 (위에서 다루었 음)가 아니라면 시간을 낭비 할 가능성이 더 큰 유지 보수 개발자의 관점에서 고려하십시오. try/ catch문제 가 아니었다면 필요하지 않을 수도 있습니다. 소스 코드 ... 그중 하나는 4 줄의 상용구 쓰레기를 추가로 가지고 있습니다!

점점 더 많은 필드가 클래스에 도입됨에 따라이 모든 보일러 플레이트 가비지 (소스 및 디스 어셈블 된 코드 모두)가 합리적인 수준을 훨씬 넘어 누적됩니다. 필드 당 4 개의 추가 줄, 항상 같은 줄입니다 ... 우리는 반복하지 않도록 배웠습니까? 나는 우리가 숨길 수있는 가정 try/ catch우리뿐만 아니라 단지 예외 (즉, 사용하지 있습니다 ... 일부 홈 양조 추상화 뒤,하지만 Int.TryParse).

이것은 복잡한 예가 아닙니다. try/ 에서 새 클래스를 인스턴스화하려는 시도를 보았습니다 catch. 생성자 내부의 모든 코드가 컴파일러에 의해 자동으로 적용되는 특정 최적화에서 실격 될 수 있음을 고려하십시오. 컴파일러가 지시 된대로 정확히 수행하는 것과 달리 컴파일러가 느리다는 이론을 일으키는 더 좋은 방법은 무엇입니까 ?

생성자에 의해 예외가 발생하고 그 결과로 일부 버그가 트리거된다고 가정하면 열악한 유지 관리 개발자는이를 추적해야합니다. 즉,의 스파게티 코드와는 달리으로, 같은 쉬운 일이되지 않을 수도 있습니다 고토 악몽, try/ catch에 혼잡이 발생할 수 있습니다 세 가지 차원 이 다른 클래스와 메소드를 같은 방법의 단지 다른없는 부분으로 스택을 이동하지만, 수 있기 때문에, , 모두는 유지 보수 개발자에 의해 관찰 될 것이다 어려운 방법 ! 그러나 우리는 "goto는 위험하다"라고 들었습니다, heh!

마지막으로 내가 언급했듯이 try/ 최적화를 비활성화하도록 설계된catch 이점이 있습니다 ! 당신이 원한다면 그것은 디버깅 보조 도구입니다 ! 그것이 그것이 설계된 이유이고 그것이 사용되어야하는 것입니다 ...

그것도 긍정적 인 점이라고 생각합니다. 멀티 스레드 애플리케이션을위한 안전하고 건전한 메시지 전달 알고리즘을 손상시킬 수있는 최적화를 비활성화하고 가능한 경쟁 조건을 포착하는 데 사용할 수 있습니다.;) 이것이 try / catch를 사용하는 유일한 시나리오입니다. 그것조차 대안이 있습니다.


무엇 최적화는 수행 try, catchfinally비활성화?

AKA

어떻게하다 try, catchfinally보조 디버깅 유용?

쓰기 장벽입니다. 이것은 표준에서 비롯됩니다.

12.3.3.13 Try-catch 문

다음 형식의 문장 stmt 의 경우 :

try try-block
catch ( ... ) catch-block-1
... 
catch ( ... ) catch-block-n
  • 의 명확한 할당 상태 V 의 시작 부분에 시도-블록 의 명확한 할당 상태와 동일한 V 의 시작 부분에 STMT .
  • 의 명확한 지정 상태 V 의 시작 캐치 블록 I (임의위한 )의 확정적 할당 상태와 동일 V 의 시작 STMT .
  • 의 명확한 할당 상태 V 의 최종 지점에서 STMT은 (그리고 경우에만) 경우 확실히 할당 V가 확실히의 엔드 포인트에 할당 시도 블록 마다 캐치 블록-I (매에 내가 1에 N ).

즉, 각 try명령문 의 시작 부분에서 :

  • try명령문 에 들어가기 전에 보이는 객체에 대한 모든 할당은 완료되어야하며, 시작시 스레드 잠금이 필요하므로 경쟁 조건을 디버깅하는 데 유용합니다!
  • 컴파일러는 다음을 허용하지 않습니다.
    • try명령문 이전에 확실히 할당 된 사용하지 않는 변수 할당 제거
    • 내부 할당을 재구성하거나 통합합니다 (예 : 아직 수행하지 않은 경우 첫 번째 링크 참조).
    • 이 장벽을 넘어 할당을 호이스트하거나, 나중에 사용되지 않을 것으로 알고있는 변수에 할당을 지연하거나 (아마도) 다른 최적화를 가능하게하기 위해 나중에 할당을 선제 적으로 앞으로 이동합니다.

비슷한 이야기가 각 catch진술에 적용됩니다. 당신 내 가정 try(의이 말을하자 문 (또는 생성자하거나 호출 기능 등) 당신이 그렇지 않으면 무의미한 변수에 할당 garbage=42;), 컴파일러는 그 문은 프로그램의 관찰 행동에 얼마나 관련이없는 상관없이 제거 할 수 . 블록에 들어가기 전에 할당이 완료 되어야합니다 catch.

그 가치에 finally대해 비슷하게 비하하는 이야기를 들려 줍니다 .

12.3.3.14 Try-finally 문

다음 형식의 trystmt 의 경우 :

try try-block
finally finally-block

try-block 시작 부분에있는 v 의 명확한 할당 상태 는 stmt 시작 부분에있는 v 의 명확한 할당 상태와 동일합니다 . • finally-block 시작 부분에있는 v 의 명확한 할당 상태 는 stmt 시작 부분에있는 v 의 명확한 할당 상태와 동일합니다 . • stmt 의 끝점에서 v 의 명확한 할당 상태는 다음 중 하나 인 경우에만 확실히 할당됩니다. o vtry-block 의 끝점에서 확실히 할당됩니다. o v

명확히의 종점에 할당 된 마지막 블록 (예로서, 제어 흐름 전달한다면 고토 문)이 그 안에 시작된다 시도 블록 및 외측 단부 시도 블록은 , 다음 V가 아니라 확실히 그것에 할당 된 것으로 간주 vfinally-block 의 끝점에 확실히 할당 된 경우 제어 흐름 전송 . (이 경우에만 해당되는 것은 아닙니다 .이 제어 흐름 전송에서 다른 이유로 v 가 확실히 할당 된 경우 에도 확실히 할당 된 것으로 간주됩니다.)

12.3.3.15 Try-catch-finally 문

try - catch - finally 서술문에 대한 명확한 할당 분석 :

try try-block
catch ( ... ) catch-block-1
... 
catch ( ... ) catch-block-n
finally finally-block

명령문이 try - finally 문이 try - catch 문인 것처럼 수행됩니다 .

try { 
    try   
    try-block
    catch ( ... ) catch-block-1
    ...   
    catch ( ... ) catch-block-n
} 
finally finally-block

3

자주 호출되는 메서드 내부에 있는지는 말할 것도없이 애플리케이션의 전반적인 동작에 영향을 미칠 수 있습니다.
예를 들어, Int32.Parse를 사용하면 다른 방법으로 쉽게 잡을 수있는 항목에 대한 예외가 발생하므로 대부분의 경우 나쁜 습관으로 간주합니다.

따라서 여기에 쓰여진 모든 것을 결론
짓기 위해 : 1) try..catch 블록을 사용하여 예상치 못한 오류를 포착합니다. 성능 저하가 거의 없습니다.
2) 피할 수 있다면 예외 오류에 예외를 사용하지 마십시오.


3

그 당시 많은 사람들이 이것에 대해 물어 보았 기 때문에 얼마 전에 이것에 대한 기사를 썼습니다. http://www.blackwasp.co.uk/SpeedTestTryCatch.aspx 에서이 코드와 테스트 코드를 찾을 수 있습니다 .

결론은 try / catch 블록에 대해 약간의 오버 헤드가 있지만 너무 작아서 무시해야한다는 것입니다. 그러나 수백만 번 실행되는 루프에서 try / catch 블록을 실행하는 경우 가능하면 블록을 루프 외부로 이동하는 것을 고려할 수 있습니다.

try / catch 블록의 핵심 성능 문제는 실제로 예외를 포착 할 때입니다. 이로 인해 애플리케이션이 눈에 띄게 지연 될 수 있습니다. 물론 일이 잘못되면 대부분의 개발자 (및 많은 사용자)는 일시 중지를 곧 일어날 예외로 인식합니다! 여기서 핵심은 정상적인 작업에 예외 처리를 사용하지 않는 것입니다. 이름에서 알 수 있듯이, 그들은 예외적이며 던져지지 않도록 할 수있는 모든 것을해야합니다. 올바르게 작동하는 프로그램의 예상 흐름의 일부로 사용해서는 안됩니다.


2

작년에이 주제에 대한 블로그 항목을 만들었 습니다. 확인 해봐. 결론은 예외가 발생하지 않으면 try 블록에 대한 비용이 거의 없다는 것입니다. 랩톱에서 예외는 약 36μs였습니다. 예상보다 적을 수 있지만 얕은 스택에서 결과가 발생한다는 점을 명심하십시오. 또한 첫 번째 예외는 정말 느립니다.


귀하의 블로그에 연결할 수 없습니다 (연결 시간이 초과되었습니다. 사용 중 입니까 try/ catch너무 많이 사용 하고 있습니까? heh heh). 언어 사양 및 주제에 대한 블로그를 작성하여 측정 값을 제공 한 일부 MS MVP와 논쟁하고있는 것 같습니다. 당신의 조언과는 반대로 ... 나는 내가 한 연구가 잘못되었다는 제안에 열려 있지만 그것이 말하는 것을 보려면 당신의 블로그 항목을 읽어야 할 것입니다.
자폐증

@Hafthor의 블로그 게시물 외에도 속도 성능 차이를 테스트하기 위해 특별히 작성된 코드 가 포함 된 또 다른 블로그 게시물 이 있습니다. 결과에 따르면 예외가 5 % 만 발생하더라도 예외 처리 코드는 비 예외 처리 코드보다 전체적으로 100 배 느리게 실행됩니다. 이 기사는 구체적으로 try-catch블록 대 tryparse()방법을 대상으로 하지만 개념은 동일합니다.

2

컴파일러 오류 메시지, 코드 분석 경고 메시지 및 일상적인 허용 예외 (특히 한 곳에서 throw되고 다른 곳에서 허용되는 예외)가없는 코드를 작성, 디버그 및 유지 관리하는 것이 훨씬 쉽습니다. 더 쉽기 때문에 코드는 평균적으로 더 잘 작성되고 버그가 적습니다.

나에게 그 프로그래머와 품질 오버 헤드는 프로세스 흐름에 try-catch를 사용하는 것에 대한 주요 논쟁입니다.

예외로 인한 컴퓨터 오버 헤드는 비교해 볼 때 중요하지 않으며 일반적으로 실제 성능 요구 사항을 충족하는 응용 프로그램의 기능 측면에서 매우 작습니다.


@Ritchard T, 왜? 비교 프로그래머 품질 오버 헤드 그것이있다 무의미한.
ThunderGr 2013 년

1

저는 Hafthor의 블로그 게시물이 정말 마음에 듭니다. 이 토론에 2 센트를 더하기 위해 DATA LAYER가 한 가지 유형의 예외 (DataAccessException) 만 던지는 것이 항상 쉬웠습니다. 이런 식으로 내 비즈니스 계층은 예상되는 예외를 알고이를 포착합니다. 그런 다음 추가 비즈니스 규칙 (예 : 내 비즈니스 개체가 워크 플로에 참여하는 경우 등)에 따라 새 예외 (BusinessObjectException)를 발생 시키거나 다시 / 던지지 않고 진행할 수 있습니다.

필요할 때마다 try..catch를 사용하는 것을 망설이지 말고 현명하게 사용하십시오!

예를 들어이 메서드는 워크 플로에 참여합니다.

코멘트?

public bool DeleteGallery(int id)
{
    try
    {
        using (var transaction = new DbTransactionManager())
        {
            try
            {
                transaction.BeginTransaction();

                _galleryRepository.DeleteGallery(id, transaction);
                _galleryRepository.DeletePictures(id, transaction);

                FileManager.DeleteAll(id);

                transaction.Commit();
            }
            catch (DataAccessException ex)
            {
                Logger.Log(ex);
                transaction.Rollback();                        
                throw new BusinessObjectException("Cannot delete gallery. Ensure business rules and try again.", ex);
            }
        }
    }
    catch (DbTransactionException ex)
    {
        Logger.Log(ex);
        throw new BusinessObjectException("Cannot delete gallery.", ex);
    }
    return true;
}

2
David, try / catch 블록에서 'DeleteGallery'에 대한 호출을 래핑 하시겠습니까?
Rob

DeleteGallery는 부울 함수이기 때문에 거기에 예외를 던지는 것이 유용하지 않은 것 같습니다. 이렇게하려면 try / catch 블록에있는 DeleteGallery에 대한 호출이 필요합니다. if (! DeleteGallery (theid)) {// handle}이 더 의미있는 것 같습니다. 그 구체적인 예에서.
ThunderGr 2013 년

1

우리는 Michael L. Scott의 Programming Languages ​​Pragmatics에서 오늘날 컴파일러가 일반적인 경우에 오버 헤드를 추가하지 않는다는 것을 읽을 수 있습니다. 즉, 예외가 발생하지 않을 때를 의미합니다. 따라서 모든 작업은 컴파일 타임에 이루어집니다. 그러나 런타임에서 예외가 발생하면 컴파일러는 올바른 예외를 찾기 위해 이진 검색을 수행해야하며 이는 사용자가 만든 모든 새 throw에 대해 발생합니다.

그러나 예외는 예외이며이 비용은 완벽하게 허용됩니다. 예외없이 예외 처리를 수행하고 대신 반환 오류 코드를 사용하려는 경우 모든 서브 루틴에 대해 if 문이 필요하며 이는 실제로 실시간 오버 헤드를 발생시킵니다. if 문이 몇 가지 어셈블리 명령어로 변환되어 서브 루틴에 들어갈 때마다 수행된다는 것을 알고 있습니다.

제 영어에 대해 죄송합니다. 도움이 되길 바랍니다. 이 정보는 인용 된 책을 기반으로하며, 자세한 내용은 8.5 장 예외 처리를 참조하십시오.


컴파일러는 런타임에 그림을 벗어났습니다. 가 하는 CLR이이 예외를 처리 할 수 있도록 시도 / catch 블록에 대한 오버 헤드. C #은 .NET CLR (가상 머신)에서 실행됩니다. 예외는 없지만 예외를 처리하는 CLR의 비용이 매우 큰 경우 블록 자체의 오버 헤드가 최소화되는 것 같습니다.
ThunderGr 2013 년

-4

try / catch 블록을 사용할 필요가없는 곳에 사용될 때 가능한 가장 큰 비용 중 하나를 분석해 보겠습니다.

int x;
try {
    x = int.Parse("1234");
}
catch {
    return;
}
// some more code here...

다음은 try / catch가없는 것입니다.

int x;
if (int.TryParse("1234", out x) == false) {
    return;
}
// some more code here

중요하지 않은 공백을 세지 않고이 두 개의 동등한 코드 조각이 바이트 단위로 거의 정확히 같은 길이임을 알 수 있습니다. 후자는 4 바이트 더 적은 들여 쓰기를 포함합니다. 그것은 나쁜 일입니까?

상해에 대한 모욕을 추가하기 위해 학생은 입력을 int로 구문 분석 할 수있는 동안 반복하기로 결정합니다. try / catch가없는 솔루션은 다음과 같을 수 있습니다.

while (int.TryParse(...))
{
    ...
}

그러나 try / catch를 사용할 때 어떻게 보입니까?

try {
    for (;;)
    {
        x = int.Parse(...);
        ...
    }
}
catch
{
    ...
}

Try / catch 블록은 들여 쓰기를 낭비하는 마법의 방법이며 실패한 이유도 아직 모릅니다! 코드가 명백한 예외 오류로 중단되지 않고 심각한 논리적 결함을지나 계속 실행될 때 디버깅을 수행하는 사람이 어떻게 느끼는지 상상해보십시오. Try / catch 블록은 게으른 사람의 데이터 유효성 검사 / 위생입니다.

더 작은 비용 중 하나는 try / catch 블록이 실제로 특정 최적화를 비활성화한다는 것입니다. http://msmvps.com/blogs/peterritchie/archive/2007/06/22/performance-implications-of-try-catch-finally.aspx . 그것도 긍정적 인 점이라고 생각합니다. 멀티 스레드 애플리케이션을위한 안전하고 건전한 메시지 전달 알고리즘을 손상시킬 수있는 최적화를 비활성화하고 가능한 경쟁 조건을 포착하는 데 사용할 수 있습니다.;) 이것이 try / catch를 사용하는 유일한 시나리오입니다. 그것조차 대안이 있습니다.


1
TryParse가 try {int x = int.Parse ( "xxx"); return true;} catch {return false; } 내부적으로. 들여 쓰기는 문제가 아니라 성능과 오버 헤드뿐입니다.
ThunderGr 2013 년

@ThunderGr 또는 내가 게시 한 새 답변을 읽으십시오 . 여기에는 더 많은 링크가 포함되어 있으며, 그중 하나 Int.ParseInt.TryParse.
자폐증
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.