2014-04-08 2 views
0

StackTraceCallerInfo Attributes을 사용하여 성능을 벤치 마크했습니다.호출자 메서드 이름 가져 오기 - Reflection 및 CallerInfo 특성

놀랍게도 나는 을 사용하는 것이 훨씬 빠르다는 것을 발견했다.

public class Program 
    { 
     public static void Main(string[] args) 
     { 
      Method1(); 
     } 

     static void Method1([CallerMemberName]string memberName = "") 
     { 
      double stackTraceTimings = 0; 
      var sw = new Stopwatch(); 

      foreach(var item in Enumerable.Range(1,1000).ToList()) 
      { 
       sw.Start(); 
       var callerName = new StackFrame(1).GetMethod().Name; 
       sw.Stop(); 
       stackTraceTimings += sw.Elapsed.TotalMilliseconds; 
      } 

      Console.WriteLine("Elapsed Time for retrieving the caller name using StackFrame in 1000 iterations ={0}",stackTraceTimings/1000); 

      stackTraceTimings = 0; 
      foreach(var item in Enumerable.Range(1,1000).ToList()) 
      { 
       sw.Start(); 
       var callerName = (memberName); 
       sw.Stop(); 
       stackTraceTimings += sw.Elapsed.TotalMilliseconds; 
      } 

      Console.WriteLine("Elapsed Time for retrieving the caller name using callerInfo Attribute in 1000 iterations ={0}",stackTraceTimings/1000); 
     } 

OUTPUT : 1000 번의 반복 callerInfo 특성을 이용하여 발신자의 이름을 검색 1000 반복에 StackFrame을를 이용하여 발신자의 이름을 검색하기위한 경과 시간 = 9.48074760000001

경과 시간 = 21.7074064

내가 잘못 이해 했습니까? 선호하는 접근 방식은 CallerInfo 속성을 사용하는 것입니까?

지적 해 주신 답변에 감사드립니다.

루프에서 매번 타이머를 다시 시작해야합니다.

누가이기는가요? 아래 답변은 CallerInfo입니다. 왜냐하면 컴파일 타임 기능이기 때문에 더 빠릅니다.

경과 시간 = 1000의 반복에 callerInfo 속성을 사용하여 호출자 이름을 입수 0.00639420000000002

I 1000 반복에 StackFrame을를 이용하여 발신자의 이름 = 0.00762619999999992

경과 시간을 검색하기위한 아래의 코드 (개정)를 사용하고 위의 결과를 얻었습니다.

public class Program 
    { 
     public static void Main(string[] args) 
     { 
      Method1(); 
     } 

     static void Method1([CallerMemberName]string memberName = "") 
     { 
      double stackTraceTimings = 0; 
      var sw = new Stopwatch(); 

      foreach(var item in Enumerable.Range(1,1000).ToList()) 
      { 
       sw.Start(); 
       var callerName = new StackFrame(1).GetMethod().Name; 
       sw.Stop(); 
       Console.Write(callerName); 
       sw.Restart(); 
       stackTraceTimings += sw.Elapsed.TotalMilliseconds; 
      } 

      Console.WriteLine("Elapsed Time for retrieving the caller name using StackFrame in 1000 iterations ={0}",stackTraceTimings/1000); 


      stackTraceTimings = 0; 
      foreach(var item in Enumerable.Range(1,1000).ToList()) 
      { 
       sw.Start(); 
       var callerName = (memberName); 
       Console.Write(callerName); 
       sw.Stop(); 
       sw.Restart(); 

       stackTraceTimings += sw.Elapsed.TotalMilliseconds; 
      } 

      Console.WriteLine("Elapsed Time for retrieving the caller name using callerInfo Attribute in 1000 iterations ={0}",stackTraceTimings/1000); 
     } 
    } 
+0

CallerMemberNameAttribute "callerInfo"를 호출하고 있습니까? 혼란스러워. – Will

답변

1

두 번째 루프 전에 타이머를 재설정해야합니다. sw.Start은 첫 번째 루프 이후 상태에서 Stopwatch으로 시작하므로 두 번째 결과는 실제로 StackTrace와 특성 기반 솔루션이 함께 합산 된 시간입니다.

CallerMethodName은 컴파일 유형의 기능이므로 확실히 빠릅니다. 결과에서 CallerMethodName에 대한 고정 코드 타이밍

은 다음과 같습니다

21.7074064 - (9.48074760000001 * 2) = 훨씬 더 빠른 그렇지 않은 2.7459111999999806

?

을 두 번 빼기 : Reset 전화가없는 경우 한 번, = 대신 += 일 경우 한 번.

업데이트

이러한 결과는 너무 큰 것 같다.Visual Studio 외부에서 실행되는 릴리스 빌드를 사용하고 있습니까? 그렇지 않으면 두 경우 모두 똑같은 결과를 얻을 수 있기 때문에 callerName은 사용되지 않으며 아마 적어도 두 번째 경우에는 최적화되지 않을 것입니다.

+0

그래, 네 말이 맞아. 가리키는 주셔서 감사합니다. 나는 그 소식을 업데이트 할 것이다. :) –

+0

오! 온라인 컴파일러를 사용하고 있습니다. 비주얼 스튜디오가 아니기 때문에 나는 그것을 사용하지 않는다. –

+0

callerName이 사용되지 않았고 no-op (최소한 두 번째 경우)에 최적화되도록 methodNames를 인쇄하고 업데이트 된 결과를 저장합니다. –

관련 문제