문제

나는 다음과 같은 유형의 코드를 여러 번 접했는데 이것이 (성능 관점에서) 좋은 습관인지 아닌지 궁금합니다.

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가지 접근 방식 간에 성능 차이가 있습니까?

도움이 되었습니까?

해결책

@브래드 터터로우

첫 번째 경우에는 예외가 손실되지 않고 생성자에 전달됩니다.나머지 부분에 대해서는 동의합니다. 두 번째 접근 방식은 스택 추적이 손실되기 때문에 매우 나쁜 생각입니다..NET으로 작업할 때 다른 프로그래머가 그렇게 하는 경우를 많이 만났고 예외의 실제 원인을 확인해야 할 때 엄청난 좌절감을 느꼈지만 예외가 발생하는 거대한 try 블록에서 다시 발생하는 경우가 있었습니다. 이제 문제가 어디서 발생했는지 전혀 알 수 없습니다.

나는 또한 성능에 대해 걱정할 필요가 없다는 Brad의 의견에 두 번째로 동의합니다.이런 종류의 미세 최적화는 끔찍한 아이디어입니다.오랫동안 실행되는 for 루프의 모든 반복에서 예외를 발생시키는 것에 대해 이야기하지 않는 한, 예외 사용으로 인해 성능 문제가 발생할 가능성은 거의 없습니다.

성능 최적화가 필요함을 나타내는 지표가 있는 경우 항상 성능을 최적화한 다음 원인으로 입증된 지점에 도달하십시오.

무언가를 나노초 더 빠르게 실행하는 것보다 쉬운 디버깅 기능(즉, 스택 추적을 숨기지 않음)을 갖춘 읽기 가능한 코드를 갖는 것이 훨씬 낫습니다.

예외를 사용자 정의 예외로 래핑하는 방법에 대한 마지막 참고 사항...이는 특히 UI를 다룰 때 매우 유용한 구성이 될 수 있습니다.알려진 모든 합리적인 예외 사례를 일부 기본 사용자 지정 예외(또는 해당 기본 예외에서 확장된 예외)로 래핑하면 UI에서 이 기본 예외를 포착할 수 있습니다.예외가 발견되면 사용자에게 ReadableMessage 속성 또는 해당 라인에 따른 정보를 표시하는 수단을 제공해야 합니다.따라서 UI가 예외를 놓칠 때마다 수정해야 하는 버그로 인한 것이며, 예외를 포착할 때마다 UI에서 적절하게 처리할 수 있고 처리해야 하는 알려진 오류 조건입니다.

다른 팁

분명히 새 객체(새 예외)를 생성하면 페널티가 발생하므로 프로그램에 추가하는 모든 코드 줄에서와 마찬가지로 예외를 더 잘 분류하면 추가 작업에 대한 비용을 지불하는지 결정해야 합니다.

그러한 결정을 내리기 위한 조언으로, 새 객체가 예외에 대한 추가 정보를 전달하지 않는 경우 새 예외 생성을 잊어버릴 수 있습니다.

그러나 다른 상황에서는 예외 계층 구조를 갖는 것이 클래스 사용자에게 매우 편리합니다.지금까지 고려한 시나리오 중 어느 것도 좋지 않은 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
}

David처럼 저는 두 번째와 세 번째가 더 나은 성능을 발휘한다고 가정합니다.하지만 세 사람 중 어느 한 사람이 그것에 대해 걱정하며 시간을 보낼 만큼 성과가 좋지 않은 사람이 있을까요?성능보다 걱정할 문제가 더 크다고 생각합니다.

FxCop은 원래 스택 추적이 손실되지 않도록 항상 두 번째 접근 방식보다 세 번째 접근 방식을 권장합니다.

편집하다:명백히 잘못된 내용을 제거했고 Mike는 친절하게 지적해 주었습니다.

하지 마세요:

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

스택 추적이 손실됩니다.

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

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

그냥 throw하면 됩니다. 새 사용자 정의 예외의 내부 예외가 되도록 하려면 예외 변수만 전달하면 됩니다.

다른 사람들이 언급했듯이 기존 객체를 다시 던지는 것이므로 최상의 성능은 맨 아래에서 나옵니다.중간 것은 스택을 느슨하게 하기 때문에 가장 정확하지 않습니다.

코드에서 특정 종속성을 분리하려는 경우 개인적으로 사용자 지정 예외를 사용합니다.예를 들어 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
}

첫 번째 예제의 throw에는 새 CustomException 객체 생성에 따른 오버헤드가 있습니다.

두 번째 예에서 다시 던지면 Exception 유형의 예외가 발생합니다.

세 번째 예제에서 다시 던지면 "일부 코드"에서 발생한 것과 동일한 유형의 예외가 발생합니다.

따라서 두 번째와 세 번째 예에서는 더 적은 리소스를 사용합니다.

기다리다....예외가 발생하면 왜 성능에 신경을 쓰나요?일반적인 애플리케이션 흐름의 일부로 예외를 사용하지 않는 한(모범 사례에 비해 WAYYYY)

나는 성공에 관한 성능 요구 사항만 보았지만 실패에 관한 성능 요구 사항은 본 적이 없습니다.

순전히 성능 관점에서 볼 때 세 번째 경우가 가장 성능이 좋다고 생각합니다.나머지 두 개는 스택 추적을 추출하고 새 객체를 생성해야 하는데, 둘 다 잠재적으로 상당히 시간이 많이 걸릴 수 있습니다.

이 세 가지 코드 블록에는 매우 서로 다른 (외부) 동작을 비교하는 것은 QuickSort가 레드-블랙 트리에 항목을 추가하는 것보다 더 효율적인지 묻는 것과 같습니다.옳은 일을 선택하는 것만큼 중요한 것은 아닙니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top