7

나는 다음과 같은 유형의 코드를 여러 번 보았고 이것이 성능면에서 좋은 것인지 아닌지 궁금하다.

try
{
    ... // some code
}
catch (Exception ex)
{
    ... // Do something
    throw new CustomException(ex);
}

기본적으로, 코더가하는 일은 사용자 정의 예외에서 예외를 포함하고 다시 던지는 것입니다.

성능면에서이 점과 다음 두 점과의 차이점은 무엇입니까?

try
{
    ... // some code
}
catch (Exception ex)
{
    .. // Do something
    throw ex;
}

또는

try
{
    ... // some code
}
catch (Exception ex)
{
    .. // Do something
    throw;
}

기능적 또는 코딩 모범 사례에 대한 논증을 제외하고 3 가지 접근 방식간에 성능 차이가 있습니까?

8 답변


10

@ 브래드 터 터우

첫 번째 경우에는 예외가 손실되지 않고 생성자에 전달됩니다. 나머지 부분에 대해서는 동의 하겠지만, 두 번째 방법은 스택 추적이 손실되어 매우 나쁜 생각입니다. .NET으로 작업했을 때 나는 다른 프로그래머가 그랬던 많은 경우를 만났습니다. 그리고 예외의 진정한 원인을보고 싶을 때 끝까지 나를 좌절 시켰습니다. 거대한 try 블록에서 다시금 발견되었습니다. 이제 문제가 어디서 발생했는지 전혀 알 수 없습니다.

브래드 (Brad)의 두 번째 언급은 성능에 대해 걱정할 필요가 없다는 점입니다. 이러한 종류의 미세 최적화는 까다로운 아이디어입니다. 오랫동안 실행되는 for 루프의 모든 반복에서 예외를 throw하는 것에 대해 언급하지 않는 한, 예외 사용 방법으로 인해 성능 문제가 발생하지 않을 것입니다.

성능을 최적화 할 필요가 있다는 것을 나타내는 메트릭스가있을 때 항상 성능을 최적화 한 다음, 그 원인이 입증 된 부분을 누르십시오.

쉬운 디버깅 기능 (IE는 스택 추적을 숨기지 않음)으로 읽을 수있는 코드를 갖는 것이 훨씬 더 좋습니다. 대신 나노초를 빠르게 실행하십시오.

예외를 사용자 정의 예외로 래핑하는 것에 대한 마지막 참고 사항 ... 특히 UI를 처리 할 때 매우 유용한 구조가 될 수 있습니다. 알려진 모든 합리적인 예외 상황을 기본 사용자 정의 예외 (또는 상기 기본 예외에서 확장 된 예외)로 래핑 할 수 있으며 UI는이 기본 예외를 잡을 수 있습니다. 잡히면 예외는 사용자에게 정보를 표시하는 방법, ReadableMessage 속성 또는 그 라인을 따라 무엇인가를 제공해야합니다. 따라서 UI에서 예외가 누락 될 때마다 수정해야 할 버그가 있기 때문에 예외가 발생할 때마다 UI에 의해 올바르게 처리되고 처리되어야하는 알려진 오류 상태입니다.


2

분명히 새로운 객체 (새로운 Exception) 생성의 형벌을 받게되므로 프로그램에 추가하는 모든 코드 행과 똑같이 예외의 더 나은 분류가 추가 작업에 대해 지불해야하는지 결정해야합니다.

그 결정을 내리기위한 충고로서 새로운 객체가 예외에 대한 추가 정보를 가지고 있지 않다면 새로운 예외를 만드는 것을 잊어 버릴 수 있습니다.

그러나 다른 상황에서는 예외 계층 구조를 사용하는 것이 클래스 사용자에게 매우 편리합니다. Facade 패턴을 구현한다고 가정 해 봅시다. 지금까지 고려한 시나리오 중 어느 것도 좋지 않습니다.

  1. 귀중한 정보를 잃어 버리기 때문에 Exception 객체로서 모든 예외를 발생시키는 것은 좋지 않습니다.
  2. 당신이 잡는 모든 종류의 물건을 모으는 것도 좋지도 않습니다. 그렇게하면 당신이 파사드를 만드는 데 실패하고 있기 때문입니다.

이 가상의 경우에는 더 나은 방법은 시스템의 내부 복잡성에서 사용자를 추상화하여 생성 된 예외의 종류에 대해 알 수있는 예외 클래스 계층 구조를 만드는 것입니다.

참고 사항 :

필자는 논리를 구현하기 위해 예외 (Exception 클래스에서 파생 된 클래스의 계층 구조) 사용을 개인적으로 싫어합니다. 이 경우처럼 :

try {
        // something that will raise an exception almost half the time
} catch( InsufficientFunds e) {
        // Inform the customer is broke
} catch( UnknownAccount e ) {
        // Ask for a new account number
}


2

데이빗처럼, 나는 두 번째와 세 번째가 더 잘 수행된다고 생각합니다. 그러나 세 사람 중 누구도 그 일에 대해 걱정할 시간을 낭비하지 않을 수 있습니까? 걱정할 성능보다 큰 문제가 있다고 생각합니다.

FxCop은 원래 스택 추적을 잃지 않도록 두 번째 세 번째 접근법을 항상 권장합니다.

편집 : 그냥 평범한 잘못이었던 물건을 제거하고 마이크가 친절하게 지적했다.


2

하지 마십시오 :

try
{
    // some code
}
catch (Exception ex) { throw ex; }

스택 추적을 잃게됩니다.

대신 다음을 수행하십시오.

try
{
    // some code
}
catch (Exception ex) { throw; }

던지기 만하면됩니다. 예외를 새로운 사용자 정의 예외의 내부 예외로 사용하려면 예외 변수를 전달하면됩니다.


  • 작은 추가 - ex를 제거하면 사용되지 않는 변수 경고가 생성됩니다. try {// some code} catch (예외) {throw; } - Dennis
  • 좋은 지적 - 나는 복사 - 붙여 넣기에서 그것을 놓쳤다. - Keith

1

다른 사람들이 말했듯이, 최상의 성능은 기존 객체를 재실행하기 때문에 가장 낮은 성능을 발휘합니다. 스택이 느슨해지기 때문에 가운데 쪽이 가장 정확하지 않습니다.

개인적으로 코드의 특정 종속성을 분리하려면 사용자 정의 예외를 사용합니다. 예를 들어 XML 파일에서 데이터를로드하는 메소드가 있습니다. 이것은 여러 가지 다른 방식으로 잘못 될 수 있습니다.

디스크 (FileIOException)에서 읽지 못하고 사용자가 허용되지 않는 곳 (SecurityException)에서 파일에 액세스하려고 시도 할 수 있습니다. 파일이 손상 될 수 있습니다 (XmlParseException). 잘못된 형식 (DeserialisationException)의 데이터 일 수 있습니다.

이 경우 호출 클래스가이 모든 것을 이해하기 쉽도록이 예외는 모두 단일 사용자 정의 예외 (FileOperationException)를 다시 발생시켜 호출자가 System.IO 또는 System.Xml에 대한 참조를 필요로하지 않지만 여전히 열거 형 및 중요한 정보를 통해 발생한 오류에 액세스합니다.

앞에서 언급했듯이, 이와 같이 마이크로 최적화를 시도하지 마십시오. 예외를 던지는 행위는 여기서 발생하는 가장 느린 것입니다. 최선의 개선은 예외를 피하려고 시도하는 것입니다.

public bool Load(string filepath)
{
  if (File.Exists(filepath)) //Avoid throwing by checking state
  {
    //Wrap anyways in case something changes between check and operation
    try { .... }
    catch (IOException ioFault) { .... }
    catch (OtherException otherFault) { .... }
    return true; //Inform caller of success
  }
  else { return false; } //Inform caller of failure due to state
}


0

첫 번째 예제의 throw는 새로운 CustomException 객체를 만드는 오버 헤드가 있습니다.

두 번째 예제에서 re-throw는 Exception 유형의 예외를 throw합니다.

세 번째 예제에서 re-throw는 "some code"에 의해 던져진 것과 같은 타입의 예외를 던질 것입니다.

따라서 두 번째와 세 번째 예제는 리소스를 덜 사용합니다.


0

기다려 .... 예외가 발생하면 성능에 신경을 쓰는 이유는 무엇입니까? 정상적인 애플리케이션 흐름의 일부로 예외를 사용하지 않는 한 (모범 사례에 비해 WAYYYY 임).

필자는 성공과 관련된 성능 요구 사항 만 보았지만 실패는 결코 고려하지 않았습니다.


0

순전히 성능 관점에서 보면 세 번째 사례가 가장 효과적이라고 생각합니다. 다른 두 개는 스택 추적을 추출하고 새 객체를 생성해야하는데, 둘 다 상당히 시간 소모적 일 수 있습니다.

이 세 블록의 코드는대단히다른 (외부) 행동을 비교하면 QuickSort가 빨간색 검정 나무에 항목을 추가하는 것보다 더 효율적인지 묻는 것과 같습니다. 옳은 일을 선택하는 것만 큼 중요하지 않습니다.

연결된 질문


관련된 질문

최근 질문