DateTime.UtcNow.Ticks иногда прыгает на значительную сумму - PullRequest
2 голосов
/ 04 ноября 2008

В тестируемом приложении с сильной петлей, которое печатает значение DateTime.UtcNow.Ticks, я замечаю, что значение будет скачкообразно увеличиваться раз в час или около того. Посмотрите внимательно на следующие примеры данных:

1:52:14.312 PM - 633614215343125000
1:52:14.359 PM - 633614215343593750
1:52:14.421 PM - 633614215344218750
1:52:14.468 PM - 633614215344687500
1:52:14.515 PM - 633614215998593750 <-- WAY different

Дельта составляет 653906250 тиков (65,390 секунд). Единственная причина, по которой я могу придумать, заключается в том, что служба Windows Time выполняет некоторую синхронизацию из-под моих ног.

  • Есть ли эксперты, которые могут это подтвердить?
  • Мне кажется, что дрейфовать минуту или около того примерно через час очень плохо, но так ли это здесь?

Ответы [ 5 ]

2 голосов
/ 04 ноября 2008

На самом деле, просто запустить тест с этим циклом:

static DateTime past = DateTime.UtcNow;
    static void PrintTime()
    {
        while (stopLoop == 0)
        {
            DateTime now = DateTime.UtcNow;
            Console.WriteLine("{0} - {1} d: {2}", now, now.Ticks, now - past);
            Program.past = now;
            Thread.Sleep(2000);
        }
    }

Если бы я изменил время системы в промежутках между вызовами, дельта соответственно подскочила бы. Так что если у вас запущена синхронизация времени или какой-то другой процесс, который влияет на системное время, это будет отражено в выводе.

1 голос
/ 05 ноября 2008

Эмм ...

Как вы можете измерить время таким образом, когда вы не можете точно сказать, что вы не вызывали какой-либо блокирующий системный вызов в течение этого времени (например, потенциально Console.WriteLine)?

Чтобы иметь «рабочий тест», вы должны как минимум убедиться:

  • НИЧЕГО еще не работает на вашем компьютере
  • Приоритет процесса / потока имеет значение Высокий или что-то в этом роде
  • Не вызывать системный вызов ... Выполнять только вычислительные задачи
  • Установите привязку потоков к определенному ЦП, чтобы не переключаться между ЦП

Даже если вы сделаете это, ОС будет время от времени (например, 15 мс на настольной ОС Windows с двумя ядрами) вытеснять ваш поток .... И вы все еще можете увидеть этот «скачок» в UTC Time-Stamp.

Простой переход из Userspace в Kernelspace (во время упреждающего / системного вызова) и обратно, без какой-либо существенной работы с ядром, потребует ~ 1000 циклов ЦП ...

Если ваш процесс переводится в состояние ожидания (путем вызова некоторого блокирующего ввода-вывода), это может быть ГЛАВНО гораздо хуже ...

Так что я действительно не прошёл твой "тест". ИМО это совершенно нормально.

0 голосов
/ 05 ноября 2008

Исходный вывод был перехвачен в DebugView. Мое управляемое приложение делало p / invoke вызов OutputDebugString, просто выводя DateTime.UtcNow.Ticks из узкого цикла в потоке, который также вызывал Thread.Sleep (1).

System information for \\JLECOURSXP:
Uptime:                    6 days 6 hours 22 minutes 53 seconds
Kernel version:            Microsoft Windows XP, Multiprocessor Free
Product type:              Professional
Product version:           5.1
Service pack:              3
Kernel build number:       2600
Registered organization:
Registered owner:          setup
Install date:              6/15/2007, 3:35:29 PM
IE version:                7.0000
System root:               C:\WINDOWS
Processors:                2
Processor speed:           2.9 GHz
Processor type:            Intel(R) Pentium(R) D CPU
Physical memory:           3070 MB
Video driver:              RADEON 9250 - Secondary
0 голосов
/ 04 ноября 2008

Esteban верен, смена системных часов приведет к изменению времени дельты между последовательными опросами. Служба Windows Time вносит эти изменения ежечасно? Вероятна ли дрейфующая минута в течение часа?

Чтобы отследить это на вашем компьютере, если вы отслеживали изменение дельты между проверками, вы можете установить условную точку останова на необычно высокое изменение дельты.

long delta = 0;
long ticks = 0;
long lastTicks = DateTime.UtcNow.Ticks;
while (true)
{
    ticks = DateTime.UtcNow.Ticks;
    delta = ticks - lastTicks;
    lastTicks = ticks;
    // Conditional breakpoint: delta > 100000000 Is True
    Console.WriteLine("{0} - {1}", ticks, delta);
}
0 голосов
/ 04 ноября 2008

Можете ли вы опубликовать код, чтобы показать, как вы сгенерировали эти данные? И предоставьте информацию о машине, на которой вы работаете?

Используя следующее, я не получаю то, что вы получаете.

        for (int i = 0; i < 10; i++)
        {

            Console.WriteLine(DateTime.Now.ToLongTimeString().ToString() + " - " + DateTime.UtcNow.Ticks.ToString());

            Thread.Sleep(10);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...