2009-07-10 5 views
0

나는 중첩 된 try/catch 문에 대해 생각 해왔고 JIT가 컴파일 된 IL의 최적화 또는 단순화를 수행 할 수있는 조건을 고려하기 시작했습니다..NET JIT는 중첩 된 try/catch 문을 최적화합니까?

설명하기 위해 예외 처리기와 기능적으로 동일한 다음과 같은 표현을 고려하십시오.

// Nested try/catch 
try 
{ 
    try 
    { 
    try 
    { 
     foo(); 
    } 
    catch(ExceptionTypeA) { } 
    } 
    catch(ExceptionTypeB) { } 
} 
catch(ExceptionTypeC) { } 

// Linear try/catch 
try 
{ 
    foo(); 
} 
catch(ExceptionTypeA) { } 
catch(ExceptionTypeB) { } 
catch(ExceptionTypeC) { } 

이 추가 변수 참조가 없거나 기능은 JIT는 스택 프레임이 선형 예를 축소 할 수 있다는 결론을 내릴 수, 중첩 된 try 문의 스택 프레임 내에서 호출 가정?

다음 예는 어때?

void Try<TException>(Action action) 
{ 
    try 
    { 
    action(); 
    } 
    catch (TException) { } 
} 

void Main() 
{ 
    Try<ExceptionC>(Try<ExceptionB>(Try<ExceptionA>(foo))); 
} 

내가 대리자 호출을 인라인 할 수있는 JIT 수있는 방법이 있다고 생각하지 않기 때문에이 예는 이전에 감소 할 수 없습니다. 그러나 foo()ExceptionC 일 때,이 솔루션은 선형 예와 비교할 때 더 열악합니까? 프레임에 포함 된 추가 데이터가 최소 임에도 불구하고 대리자 호출에서 스택 프레임을 찢어 버리는 데 추가 비용이 든다 고 생각됩니다.

+1

처음 두 경우에 대해 일리노이를 살펴 보셨습니까? – womp

답변

8

첫 번째 경우에는 catch 블록 내에서 아무 것도하지 않을 때 만 기능적으로 동일하다는 점에 유의해야합니다. 그렇지 않으면이 고려 :

try 
{ 
    foo(); 
} 
catch (IOException) 
{ 
    throw new ArgumentException(); // Bubbles up to caller 
} 
catch (ArgumentException) 
{ 
    Console.WriteLine("Caught"); 
} 

대 차이가 분명이 경우 지금

try 
{ 
    try 
    { 
     foo(); 
    } 
    catch (IOException) 
    { 
     throw new ArgumentException(); // Caught by other handler 
    } 
} 
catch (ArgumentException) 
{ 
    Console.WriteLine("Caught"); 
} 

하지만 catch 블록이 어떤 임의의 메소드를 호출하는 경우 JIT 의미하는 방법을 던져가 무엇인지 알을 ? 조심하는 것이 가장 좋습니다.

이렇게하면 JIT가 빈 캐치 블록에 대해 최적화를 수행하는 옵션이 생겨납니다. 이는 처음부터 강력하게 권장하지 않는 방법입니다. 나는 JIT가 나쁜 코드를 탐지하고 그것을 약간 더 빨리 실행하려고 노력하는 것을 원하지 않는다. 실제로 첫 번째 장소에서 성능 차이가 있다면.

+0

Jon 분석에 감사드립니다. 내 마음 속에서 비어있는 캐치 핸들러는 노 트로 작업을 수행하지 않았습니다. 그러나 OutOfMemoryException 및 ThreadAbortExcetpion 같은 예외는 foo() 외부의 이유로 발생할 수 있기 때문에 분석이 계속 적용됩니다. –

4

성능에 대한 try/catch/finally 영역을 이해하면 이러한 영역이 코드의 정규 실행에 투명하다는 것입니다. 즉, catch 코드에 예외가 발생하지 않으면 try/catch/finally 영역에 ZERO 코드 실행 성능에 영향을줍니다.

그러나 예외가 발생하면 런타임은 스택이 발생한 사이트에서 스택을 걷기 시작하여 메타 데이터 테이블을 검사하여 해당 사이트가 중요한 try 블록에 포함되어 있는지 확인합니다. 하나가 발견되면 (적절한 catch 블록 또는 finally 블록이있는 경우) 관련 핸들러가 식별되고 실행이이 지점으로 분기됩니다.

예외를 발생시키고 처리하는 프로세스는 성능 측면에서 비용이 많이 듭니다. 프로그래머는 예외적 인 상황 이외의 상황에서 프로그램 흐름을 신호하거나 제어하는 ​​방법으로 예외를 사용해서는 안됩니다.

+0

+1 try-catch 블록의 런타임 비용 설명 –

관련 문제