일부 단위 테스트를 수행하는 동안 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
.