Я бы добавил следующее относительно ответа MusiGenesis для времени повторной синхронизации.
Значение: какое время следует использовать для повторной синхронизации (_maxIdle
в ответе MusiGenesis)
Вы знаете, что с этим решением вы не совсем точны, поэтому вы выполняете повторную синхронизацию. Но также то, что вы неявно хотите, - это то же самое, что и решение Яна Мерсера:
уникальная временная метка, которая выделяется в строгом порядке возрастания
Следовательно, промежуток времени между двумя повторными синхронизациями (_maxIdle
Назовем его SyncTime) должен зависеть от 4 факторов:
DateTime.UtcNow
разрешение
- коэффициент точности, который вы хотите
- желаемый уровень точности
- Оценка коэффициента рассинхронизации вашей машины
Очевидно, что первым ограничением для этой переменной будет:
коэффициент рассинхронизации ‹= коэффициент точности
Например: я не хочу, чтобы моя точность была хуже 0,5 с / час или 1 мс / день и т. Д. (На плохом английском: я не хочу ошибаться больше, чем 0,5 с / час = 12 с / день).
Таким образом, вы не можете достичь большей точности, чем секундомер на вашем ПК. Это зависит от вашего коэффициента рассинхронизации, который может быть непостоянным.
Еще одно ограничение - минимальное время между двумя повторными синхронизациями:
Synctime> = DateTime.UtcNow
разрешение
Здесь точность и точность связаны, потому что, если вы используете высокую точность (например, для хранения в БД), но более низкую точность, вы можете нарушить оператор Иэна Мерсера, который является строгим порядком возрастания.
Примечание. Кажется, DateTime.UtcNow может иметь значение Res по умолчанию больше 15 мс (1 мс на моем компьютере) Перейдите по ссылке: Высокая точность DateTime.UtcNow
Возьмем пример:
Представьте себе соотношение рассинхронизации, о котором говорилось выше.
Примерно через 10 часов он был впереди на 5 секунд.
Скажем, мне нужна точность в микросекундах. Разрешение моего таймера составляет 1 мс (см. Примечание выше)
Итак, по пунктам:
DateTime.UtcNow
разрешение: 1 мс
- коэффициент точности> = коэффициент рассинхронизации, давайте возьмем наиболее точный из возможных: коэффициент точности = коэффициент рассинхронизации
- желаемый уровень точности: 1 мкс
- Оценка коэффициента рассинхронизации вашего компьютера: 0,5 с / час (это тоже моя точность)
Если вы сбрасываете каждые 10 с, представьте, что у вас 9,999 с, за 1 мс до сброса. Здесь вы звоните в течение этого интервала. Время, в течение которого ваша функция будет строить график, опережает: 0,5 / 3600 * 9,999 с или 1,39 мс. Вы бы отобразили время 10.000390сек. Если после тика UtcNow вы совершите звонок в течение 390 микросекунд, у вас будет номер ниже предыдущего. Хуже, если этот коэффициент рассинхронизации является случайным в зависимости от загрузки процессора или других факторов.
Теперь предположим, что я установил минимальное значение SyncTime> я выполняю повторную синхронизацию каждые 1 мс.
Если я буду думать так же, то я опередил бы время на 0,139 микросекунды - хуже, чем мне нужна точность. Поэтому, если я вызываю функцию при 9,999 мс, то есть за 1 микросекунду до сброса, я построю график 9,999. И сразу после этого я построю 10.000. У меня будет хороший порядок.
Итак, здесь другое ограничение: коэффициент точности x уровень точности SyncTime ‹, скажем так, чтобы быть уверенным, потому что число может быть округлено в большую сторону, что коэффициент точности x уровень точности SyncTime‹ / 2 является хорошим.
Проблема решена.
Итак, краткий обзор:
- Получите разрешение вашего таймера.
- Вычислите оценку коэффициента рассинхронизации.
- коэффициент точности> = оценка коэффициента несинхронизации, Наилучшая точность = коэффициент несинхронизации
- Выберите свой уровень точности, учитывая следующее:
- разрешение-таймера ‹= SyncTime‹ = PrecisionLevel / (2 * коэффициент точности)
- Наилучшая точность, которую вы можете достичь, - это разрешение таймера * 2 * несинхронизация.
Для указанного выше соотношения (0,5 / час) правильное значение SyncTime составляет 3,6 мс, поэтому округляется до 3 мс.
С указанным выше соотношением и разрешением таймера 1 мс. Если вам нужен уровень точности с одним тиком (0,1 микросекунды), вам потребуется коэффициент рассинхронизации не более: 180 мс / час.
В своем последнем ответе на собственный ответ MusiGenesis заявляет:
@Hermann: Я проводил аналогичный тест в течение последних двух часов (без коррекции сброса), и таймер на основе секундомера работает только примерно на 400 мс вперед через 2 часа, поэтому сам перекос кажется переменным (но все еще довольно суровый). Я очень удивлен, что перекос настолько плох; Думаю, поэтому Секундомер находится в System.Diagnostics. - MusiGenesis
Таким образом, точность секундомера приближается к 200 мс / час, почти 180 мсек / час. Есть ли ссылка на то, почему наш номер и этот номер так близки? Не знаю. Но этой точности нам достаточно для достижения Tick-Precision
Наилучший уровень точности: в приведенном выше примере это 0,27 микросекунды.
Однако что произойдет, если я вызову его несколько раз между 9,999 мс и повторной синхронизацией.
2 вызова функции могут закончиться тем, что возвращается один и тот же TimeStamp, время будет 9,999 для обоих (поскольку я не вижу большей точности). Чтобы обойти это, вы не можете коснуться уровня точности, потому что он связан с SyncTime указанным выше отношением. Поэтому вам следует реализовать решение Яна Мерсера для этого случая.
Пожалуйста, не стесняйтесь комментировать мой ответ.
person
user3091460
schedule
09.03.2014