2013-05-21 2 views
4

여기에 메서드 반환 작업에 대한 벤치 마크가 있지만 후드 아래에서 동기화되어 실행됩니다. UsingAsyncModifier보다 UsingTaskFromResult 10 배 빠른"동기화 된"비동기 메서드의 오버 헤드는 무엇입니까?

Repeat 10000 times. 
UsingAsyncModifier: 00:00:00.1043980 
UsingTaskCompletionSource: 00:00:00.0095270 
UsingTaskFromResult: 00:00:00.0089460 

반복 10,000 번 :

class MainClass 
{ 
    public static async Task<int> UsingAsyncModifier() 
    { 
     return 10; 
    } 

    public static Task<int> UsingTaskCompletionSource() 
    { 
     TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); 
     tcs.SetResult(10); 
     return tcs.Task; 
    } 

    public static Task<int> UsingTaskFromResult() 
    { 
     return Task.FromResult(10); 
    } 

    public static void Main(string[] args) 
    { 
     DateTime t = DateTime.Now; 
     const int repeat = 10000; // Results volatile while repeat grows. 
     Console.WriteLine("Repeat {0} times.", repeat); 

     int j = 0; 
     for (int i = 0; i < repeat; i++) 
     { 
      j += UsingAsyncModifier().Result; 
     } 
     Console.WriteLine("UsingAsyncModifier: {0}", DateTime.Now - t); 
     t = DateTime.Now; 

     for (int i = 0; i < repeat; i++) 
     { 
      j += UsingTaskCompletionSource().Result; 
     } 
     Console.WriteLine("UsingTaskCompletionSource: {0}", DateTime.Now - t); 
     t = DateTime.Now; 

     for (int i = 0; i < repeat; i++) 
     { 
      j += UsingTaskFromResult().Result; 
     } 
     Console.WriteLine("UsingTaskFromResult: {0}", DateTime.Now - t); 
    } 
} 

출력 (10,000/100,000/1000,000 번 반복).

Repeat 100000 times. 
UsingAsyncModifier: 00:00:00.1676000 
UsingTaskCompletionSource: 00:00:00.0872020 
UsingTaskFromResult: 00:00:00.0870180 

반복을 10 번, UsingTaskFromResult 배보다 빠른 UsingAsyncModifier.

Repeat 1000000 times. 
UsingAsyncModifier: 00:00:00.8458490 
UsingTaskCompletionSource: 00:00:00.8870980 
UsingTaskFromResult: 00:00:00.9027320 

반복을 백만 번, UsingAsyncModifier UsingTaskFromResult보다 약간 더 빠르게.

내 생각에 async 수정자가 Task.FromResult()과 같은 완료된 작업을 만들었습니다. 그러나 벤치 마크는 내 생각을 증명하지 못합니다. 왜? I는 DateTime를 사용하여 유사한 결과를 볼 동안

+7

매우 높은 반복에있는 시간이 거의 동일했다 있다는 사실 가능성이 낮은 반복의 차이는 소음, GC를 기반으로하고 있다는 것을 의미 그것을 읽어 비동기 방식의 경우에는 해당되지 않습니다 컬렉션, 컨텍스트 스위치 및 기타 오류를 벤치마킹 프레임 워크와 비교합니다. 또한'DateTime.Now'는 short라는 시간을 측정 할만큼 정밀도가 충분하지 않습니다. * 빠른 속도로 실행되는 벤치마킹 코드 조각은 * 정말 * 어렵습니다. 본질적으로, 당신의 테스트는 실제로 의미있는 것을 말하는 것이 아닙니다. 오류 범위가 너무 커서 결과를 효과적으로 의미가 없게됩니다. – Servy

+0

첫 번째 방법이 너무 간단하여 컴파일러가 최적화 할 수는 없습니다. 동기식으로 실행될 수도 있습니다 (백그라운드 작업이 너무 빨리 실행되어 비동기 요청이 완료되기 전에 완료된 것으로 호출자에게 표시 될 수 있음을 알고 있습니다). @Servy가 시사 하듯이 이러한 조건에서 테스트가 실제로 의미가있는 것은 아닙니다. –

+0

@DanPuzey,'async'-ed 메소드없이'await'가 동 기적으로 실행됩니다. 반환 된 결과를 래핑하는 작업을 반환하지 않고는 실행할 수 없습니다.나는 '비동기 (async)'를 사용하여 ppl이 내 머리를 부러 뜨리지 않고 내가 쓴 것을 정확하게 이해했다. 더 길게 덜 애매하게 쓰는 법 –

답변

2

시간 측정 용 Stopwatch를 사용하여 반복을 UsingAsyncModifier()도 1 000 000와 (UsingTaskCompletionSource() 또는 UsingTaskFromResult() 모두 도시 동일한 appr. 지속 시간을 사용하기보다는)의 2 배 이상의 시간 기간을 취하는 것이 도시 반복 여기

것은 출력 : Stopwatch

class Program 
{ 
    public static async Task<int> UsingAsyncModifier() 
    { 
     return 10; 
    } 

    public static Task<int> UsingTaskCompletionSource() 
    { 
     TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); 
     tcs.SetResult(10); 
     return tcs.Task; 
    } 
    public static Task<int> UsingTaskFromResult() 
    { 
     return TaskEx.FromResult(10); 
    } 
    static void Main(string[] args) 
    { 
     //DateTime t = DateTime.Now; 
     Stopwatch timer = new Stopwatch(); 
     const int repeat = 1000*1000; // Results volatile while repeat grows. 
     Console.WriteLine("Repeat {0} times.", repeat); 

     int j = 0; 
     //DateTime t = DateTime.Now; 
     timer.Start(); 
     for (int i = 0; i < repeat; i++) 
     { 
      j += UsingAsyncModifier().Result; 
     } 
     timer.Stop(); 
     Console.WriteLine("UsingAsyncModifier: {0}" 
          , timer.ElapsedMilliseconds); 
     //t = DateTime.Now; 
     timer.Reset(); 

     j = 0; 

     timer.Start(); 
     for (int i = 0; i < repeat; i++) 
     { 
      j += UsingTaskCompletionSource().Result; 
     } 
     timer.Stop(); 
     Console.WriteLine("UsingTaskCompletionSource: {0}" 
          , timer.ElapsedMilliseconds); 
     //t = DateTime.Now; 
     timer.Reset(); 
     j = 0; 
     timer.Start(); 
     for (int i = 0; i < repeat; i++) 
     { 
      j += UsingTaskFromResult().Result; 
     } 
     timer.Stop(); 
     Console.WriteLine("UsingTaskFromResult: {0}" 
          , timer.ElapsedMilliseconds); 

     Console.ReadLine(); 
    } 
} 
를 사용하여 코드와

Repeat 1000000 times. 
UsingAsyncModifier: 5458 
UsingTaskCompletionSource: 2838 
UsingTaskFromResult: 2556 

에서

스티븐 Toub는 그의 "Async Performance: Understanding the Costs of Async and Await는"설명 :

동기 코드 작업, 빈기구와 방법이 실질적으로 무료 이다. 이

훨씬 더 자세한

관련 문제