DateTime.Now가 함수의 성능을 측정하는 가장 좋은 방법입니까?


474

병목 현상을 찾아야하며 가능한 측정 시간을 정확하게 측정해야합니다.

다음 코드 스 니펫이 성능을 측정하는 가장 좋은 방법입니까?

DateTime startTime = DateTime.Now;

// Some execution process

DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);

그건 그렇고, 무언가를 찾고 있지 않으면 빠르고 더러운 성능 카운터를 사용할 수 있습니다.
Jonathan C Dickinson

1
더 높은 정밀도가 필요한 경우 Stopwatch.GetTimestamp를 사용하십시오. 그렇지 않으면 대답이 좋습니다.
dbasnett

@dbasnett 답변을 더 자세히 볼 수 있습니까?
David Basarab

위의 예제에서 start 및 endtime을 long으로 변경하고 DateTime.Now 대신 Stopwatch.GetTimestamp를 할당하십시오. 소요 시간은 (종료) /Stopwatch.Frequency입니다.
dbasnett

답변:


649

아뇨. 스톱워치 사용 (에서 System.Diagnostics)

Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

스톱워치는 고정밀 타이머가 있는지 자동으로 확인합니다.

시간대, DST 등 으로 수행 해야하는 작업으로 인해 DateTime.Now종종 속도가 약간 느리다는 것을 언급 할 가치가 DateTime.UtcNow있습니다 .

DateTime.UtcNow의 해상도는 일반적으로 15ms입니다. 자세한 내용 은 정밀도에 대한 John Chapman의 블로그 게시물을 참조하십시오 DateTime.Now.

재미있는 퀴즈 : DateTime.UtcNow하드웨어가 고주파수 카운터를 지원하지 않으면 스톱워치가 다시 사용됩니다 . 정적 필드 Stopwatch.IsHighResolution 을 보면 Stopwatch가 하드웨어를 사용하여 고정밀도를 달성하는지 확인할 수 있습니다 .


3
하나의 PerformWork ()를 배치합니다. "가열"에 대한 스톱워치 이전.
DiVan

2
또한 PerformWork()매우 짧은 경우 반복해서 전화를 걸고 통화 일괄 처리의 평균을 계산할 수있는 권장 사항을 추가해야 합니다. 또한 Stopwatch타이밍 측정을 방해하는 스트로브 효과를 피하기 위해 전화를 시작 / 중지하지 않고 전체 통화 시간을 측정하십시오.
devgeezer

1
스톱워치는 멀티 코어에서 스레드 세이프가 아닙니다. 참조 stackoverflow.com/questions/6664538/...을 하고 stackoverflow.com/questions/1149485/...
파벨 Savara

1
sw.ElapsedMilliseconds; 수
Flappy

2
@Pavel, 분명히, Stopwatch는 Windows 7 및 Windows 8을 실행하는 최신 멀티 코어 프로세서에서 최상의 솔루션 (낮은 오버 헤드 및 고정밀)으로 Microsoft에서 권장합니다. msdn.microsoft.com/en-us/library/windows/ desktop /…
Ron

91

빠르고 더러운 것을 원한다면 스톱워치를 사용하여 정밀도를 높이는 것이 좋습니다.

Stopwatch sw = new Stopwatch();
sw.Start();
// Do Work
sw.Stop();

Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);

또는 좀 더 정교한 것이 필요한 경우 ANTS 와 같은 타사 프로파일 러를 사용하는 것이 좋습니다 .


56

이 기사에서는 우선 세 가지 대안 Stopwatch, DateTime.NowAND 를 비교해야한다고 말합니다 DateTime.UtcNow.

또한 스톱워치가 DateTime.UtcNow + 일부 추가 처리를 사용하는 경우도 있습니다 (성능 카운터가 존재하지 않는 경우). 이 경우 DateTime.UtcNow가 가장 좋은 옵션이라는 것이 분명합니다 (다른 사용 + 일부 처리 때문에)

그러나 결과적으로 카운터는 거의 항상 존재합니다. 고해상도 성능 카운터 및 .NET 스톱워치와 관련된 존재에 대한 설명은 무엇입니까? .

성능 그래프는 다음과 같습니다. 저비용 성능 UtcNow가 다른 제품과 비교 한 결과를 확인하십시오.

여기에 이미지 설명을 입력하십시오

X 축은 샘플 데이터 크기이고 Y 축은 예제의 상대 시간입니다.

Stopwatch더 좋은 점 은 더 높은 분해능 시간 측정을 제공한다는 것입니다. 다른 하나는 더 많은 OO 특성입니다. 그러나 OO 래퍼를 만드는 UtcNow것은 어렵지 않습니다.


첫 번째 링크가 끊어진 것 같습니다.
피터 Mortensen

1
그렇습니다. 타임머신은 내가 추측 할 수 있다는 것을 보여줄 수있다. 왜 당신이 "세"를 편집하는지, 여기서는 필요하지 않습니다.
발렌틴 쿠 주브

18

벤치마킹 코드를 유틸리티 클래스 / 방법으로 푸시하는 것이 유용합니다. StopWatch클래스 일 필요는 없습니다Disposed 또는 Stopped오류에. 그래서, 간단한 코드에 시간이 몇 가지 조치가 있다

public partial class With
{
    public static long Benchmark(Action action)
    {
        var stopwatch = Stopwatch.StartNew();
        action();
        stopwatch.Stop();
        return stopwatch.ElapsedMilliseconds;
    }
}

샘플 호출 코드

public void Execute(Action action)
{
    var time = With.Benchmark(action);
    log.DebugFormat(“Did action in {0} ms.”, time);
}

확장 방법 버전은 다음과 같습니다.

public static class Extensions
{
    public static long Benchmark(this Action action)
    {
        return With.Benchmark(action);
    }
}

그리고 샘플 호출 코드

public void Execute(Action action)
{
    var time = action.Benchmark()
    log.DebugFormat(“Did action in {0} ms.”, time);
}

1
더 나은 입도는 어떻습니까? 많은 일이 1ms 미만으로 발생합니다.
Henrik

Elapsed 속성을 반환하면 TimeSpan입니다. 난 그냥 당신에게 패턴을 보여주고 있습니다. 재미있게 구현하십시오.
Anthony Mastrean

Elapsed.TotalMilliseconds더 높은 정밀도를 위해 반환 합니다. 이 질문도 함께보십시오 stackoverflow.com/questions/8894425/…
nawfal

16

스톱워치 기능이 더 나은 (고정밀도) 일 것이다. 나는 또한 비록 (그냥 인기 프로파일 중 하나를 다운로드하는 것이 좋습니다 것 DotTrace개미는 내가 가장을 사용했던 사람이 ... DotTrace의 무료 평가판 완벽하게 작동하고, 다른 사람의 일부처럼 잔소리하지 않습니다).


13

System.Diagnostics.Stopwatch 클래스를 사용하십시오.

Stopwatch sw = new Stopwatch();
sw.Start();

// Do some code.

sw.Stop();

// sw.ElapsedMilliseconds = the time your "do some code" took.

11

디토 스톱워치, 더 나아졌습니다.

성능 측정과 관련하여 "// 일부 실행 프로세스"가 매우 짧은 프로세스인지 확인해야합니다.

또한 "// 일부 실행 프로세스"의 첫 번째 실행은 후속 실행보다 느릴 수 있습니다.

나는 일반적으로 루프에서 1000 번 또는 1000000 번 실행하여 메소드를 테스트하고 한 번 실행하는 것보다 훨씬 정확한 데이터를 얻습니다.


9

이것들은 모두 시간을 측정하는 좋은 방법이지만 병목 현상을 찾는 매우 간접적 인 방법입니다.

스레드에서 병목 현상을 찾는 가장 직접적인 방법은 스레드를 실행하는 것입니다. 대기하는 작업을 수행하는 동안 일시 중지 또는 중지 키로 중지하십시오. 이 작업을 여러 번 수행하십시오. 병목 현상이 X %의 시간이 걸리면 X %는 각 스냅 샷의 동작에서이를 포착 할 확률입니다.

작동 방식 및 이유에 대한 자세한 설명은 다음과 같습니다.


7

@ 션 챔버스

참고로 .NET Timer 클래스는 진단용이 아니며 다음과 같이 미리 설정된 간격으로 이벤트를 생성합니다 ( MSDN에서 ).

System.Timers.Timer aTimer;
public static void Main()
{
    // Create a timer with a ten second interval.
    aTimer = new System.Timers.Timer(10000);

    // Hook up the Elapsed event for the timer.
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

    // Set the Interval to 2 seconds (2000 milliseconds).
    aTimer.Interval = 2000;
    aTimer.Enabled = true;

    Console.WriteLine("Press the Enter key to exit the program.");
    Console.ReadLine();
}

// Specify what you want to happen when the Elapsed event is 
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}

따라서 이것은 시간이 오래 걸린다는 것을 아는 데 실제로 도움이되지 않습니다.

타이머는 System.Windows.Forms의 컨트롤로도 노출됩니다 ... VS05 / VS08의 디자이너 도구 상자에서 찾을 수 있습니다


6

이것은 올바른 방법입니다.

using System;
using System.Diagnostics;

class Program
{
    public static void Main()
    {
        Stopwatch stopWatch = Stopwatch.StartNew();

            // some other code

        stopWatch.Stop();

        // this not correct to get full timer resolution
        Console.WriteLine("{0} ms", stopWatch.ElapsedMilliseconds);

        // Correct way to get accurate high precision timing
        Console.WriteLine("{0} ms", stopWatch.Elapsed.TotalMilliseconds);
    }
}

자세한 내용은 정확한 성능 카운터를 얻기 위해 DataTime 대신 스톱워치사용하십시오 .


6

Visual Studio Team System 에는이 문제를 해결하는 데 도움이되는 몇 가지 기능이 있습니다. 기본적으로 단위 테스트를 작성하고 다른 시나리오에서 혼합하여 스트레스 또는로드 테스트의 일부로 소프트웨어에 대해 실행할 수 있습니다. 이는 애플리케이션 성능에 가장 큰 영향을 미치는 코드 영역을 식별하는 데 도움이 될 수 있습니다.

Microsoft의 Patterns and Practices 그룹에는 Visual Studio Team 시스템 성능 테스트 지침에 대한 지침이 있습니다.


5

방금 Vance Morrison의 블로그에서 사용 하기 쉽고 측면에서 깔끔한 작업을 수행 하는 CodeTimer 클래스 에 대한 게시물을 찾았습니다 StopWatch.


5

이것은 충분히 전문적이지 않습니다.

Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

보다 안정적인 버전은 다음과 같습니다.

PerformWork();

int repeat = 1000;

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < repeat; i++)
{
   PerformWork();
}

sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds / repeat);

실제 코드에서는 관리 힙을 알려진 상태로 변경하기 위해 GC.Collect 호출을 추가하고 ETW 프로파일에서 다른 코드 간격을 쉽게 분리 할 수 ​​있도록 절전 호출을 추가합니다.


4

나는 이런 종류의 성능 검사를 거의하지 않았습니다 ( "이것은 느리고 빨리 만듭니다"라고 생각하는 경향이 있으므로).

구글은 성능 점검을위한 많은 리소스 / 기사를 공개합니다.

성능 정보를 얻기 위해 pinvoke를 사용하는 많은 사람들이 언급했습니다. 내가 공부하는 많은 자료는 perfmon을 사용해서 만 언급합니다.

편집하다:

스톱워치의 대화를 보았습니다. 나는 무언가를 배웠다 :)

좋은 기사처럼 보입니다


4

내 프로그램에서 사용하는 방법은 여기에 표시된대로 StopWatch 클래스를 사용하는 것입니다.

Stopwatch sw = new Stopwatch();
sw.Start();


// Critical lines of code

long elapsedMs = sw.Elapsed.TotalMilliseconds;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.