태그 보관물: precision

precision

C # DateTime.Now 정밀도 공통 분모 CPU를 위해

일부 단위 테스트를 수행하는 동안 DateTime.UtcNow에서 예기치 않은 동작이 발생했습니다. DateTime.Now/UtcNow를 빠르게 연속적으로 호출하면보다 정확한 밀리 초 단위를 캡처하는 대신 예상보다 긴 시간 간격 동안 동일한 값을 반환하는 것 같습니다.

정확한 시간 측정을 수행하는 데 더 적합한 Stopwatch 클래스가 있다는 것을 알고 있지만 누군가가 DateTime에서이 동작을 설명 할 수 있는지 궁금합니다. DateTime.Now에 대해 문서화 된 공식 정밀도가 있습니까 (예 : 50ms 이내의 정밀도)? 왜 DateTime.Now가 대부분의 CPU 클럭이 처리 할 수있는 것보다 덜 정확할까요? 아마도 가장 낮은 공통 분모 CPU를 위해 설계 되었을까요?

public static void Main(string[] args)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    for (int i=0; i<1000; i++)
    {
        var now = DateTime.Now;
        Console.WriteLine(string.Format(
            "Ticks: {0}\tMilliseconds: {1}", now.Ticks, now.Millisecond));
    }

    stopwatch.Stop();
    Console.WriteLine("Stopwatch.ElapsedMilliseconds: {0}",
        stopwatch.ElapsedMilliseconds);

    Console.ReadLine();
}



답변

왜 DateTime.Now가 대부분의 CPU 클럭이 처리 할 수있는 것보다 덜 정확할까요?

좋은 시계는 정확 하고 정확 해야합니다 . 그것들은 다릅니다. 오래된 농담처럼 멈춘 시계는 정확히 하루에 두 번 정확하고 1 분 느린 시계는 절대 정확하지 않습니다. 그러나 1 분 느린 시계는 항상 가장 가까운 분까지 정확하지만 중지 된 시계는 유용한 정밀도가 전혀 없습니다.

DateTime이 마이크로 초까지 정확할 수 없는데 마이크로 초까지 정확 해야하는 이유는 무엇 입니까? 대부분의 사람들은 마이크로 초까지 정확한 공식 시간 신호 소스가 없습니다. 따라서의 소수점 이하 여섯 자리주고 정밀도를 지난 5하는 중입니다 쓰레기가 될 것이다 거짓말 .

DateTime의 목적은 날짜와 시간나타내는 것 입니다. 고정밀 타이밍은 DateTime의 목적이 아닙니다. 아시다시피 이것이 StopWatch의 목적입니다. DateTime의 목적은 사용자에게 현재 시간을 표시하고 다음 화요일까지의 일 수를 계산하는 등의 목적으로 날짜와 시간을 나타내는 것입니다.

간단히 말해서 “몇 시지?” 그리고 “얼마나 걸렸어?” 완전히 다른 질문입니다. 한 질문에 답하기 위해 고안된 도구를 사용하여 다른 질문에 답하지 마십시오.

질문 해 주셔서 감사합니다. 이것은 좋은 블로그 기사가 될 것입니다! 🙂


답변

DateTime의 정밀도는 실행되는 시스템에 따라 다소 다릅니다. 정밀도는 컨텍스트 전환의 속도와 관련이 있으며 약 15ms 또는 16ms입니다. (내 시스템에서는 실제로 테스트에서 약 14ms이지만 정확도가 35-40ms에 가까운 일부 랩톱을 보았습니다.)

Peter Bromberg는 이에 대해 논의하는 C #의 고정밀 코드 타이밍대한 기사를 작성 했습니다 .


답변

나는 정확한 Datetime.Now :)를 원하므로 이것을 요리했습니다.

public class PreciseDatetime
{
    // using DateTime.Now resulted in many many log events with the same timestamp.
    // use static variables in case there are many instances of this class in use in the same program
    // (that way they will all be in sync)
    private static readonly Stopwatch myStopwatch = new Stopwatch();
    private static System.DateTime myStopwatchStartTime;

    static PreciseDatetime()
    {
        Reset();

        try
        {
            // In case the system clock gets updated
            SystemEvents.TimeChanged += SystemEvents_TimeChanged;
        }
        catch (Exception)
        {                
        }
    }

    static void SystemEvents_TimeChanged(object sender, EventArgs e)
    {
        Reset();
    }

    // SystemEvents.TimeChanged can be slow to fire (3 secs), so allow forcing of reset
    static public void Reset()
    {
        myStopwatchStartTime = System.DateTime.Now;
        myStopwatch.Restart();
    }

    public System.DateTime Now { get { return myStopwatchStartTime.Add(myStopwatch.Elapsed); } }
}


답변

에서 MSDN 당신은 찾을거야 DateTime.Now대략 모든 NT 운영 체제에서 10 밀리 초 해상도를.

실제 정밀도는 하드웨어에 따라 다릅니다. 를 사용하여 더 나은 정밀도를 얻을 수 있습니다 QueryPerformanceCounter.


답변

실제로 .NET 소스를 확인하는 것보다 가치가있는 것에 대해 Eric Lippert는 이 SO 질문에 대해 DateTime이 약 30ms까지만 정확하다는 의견을 제공 했습니다 . 나노초가 정확하지 않은 이유는 “그럴 필요가 없다”는 것입니다.


답변

MSDN 문서에서 :

이 속성의 해상도는 시스템 타이머에 따라 다릅니다.

그들은 또한 Windows NT 3.5 이상에서 대략적인 해상도가 10ms라고 주장합니다. 🙂


답변

이 속성의 해상도는 기본 운영 체제에 따라 달라지는 시스템 타이머에 따라 다릅니다. 0.5에서 15 밀리 초 사이 인 경향이 있습니다 .

결과적으로 루프에서와 같이 짧은 시간 간격으로 Now 속성을 반복적으로 호출하면 동일한 값이 반환 될 수 있습니다.

MSDN 링크