Оптимизация альтернатив DateTime.Now

Коллега и я обсуждаем этот вопрос, и я надеюсь получить некоторые сторонние мнения относительно того, является ли мое предлагаемое решение хорошей идеей.

Во-первых, отказ от ответственности: я понимаю, что понятие "оптимизация DateTime.Now" звучит для некоторых из вас безумно. У меня есть пара преимущественных защит:

  1. Иногда я подозреваю, что те люди, которые всегда говорят: «Компьютеры быстры; удобочитаемость всегда важнее оптимизации», часто говорят об опыте разработки приложений, где производительность, хотя это может быть важной /em>, не является критическим . Я говорю о том, что необходимо, чтобы события происходили как можно ближе к мгновенному состоянию - например, в течение наносекунд (в некоторых отраслях это имеет значение - например, высокочастотная торговля в реальном времени).
  2. Даже с учетом этого альтернативный подход, который я опишу ниже, на самом деле вполне читабелен. Это не странный взлом, а простой метод, который работает надежно и быстро.
  3. У нас есть тесты. DateTime.Now является медленным (условно говоря). Метод ниже работает быстрее.

Теперь перейдем к самому вопросу.

Из тестов мы выяснили, что для выполнения DateTime.Now требуется примерно 25 тиков (около 2,5 микросекунд). Это, конечно, усреднено от тысячи до миллионов звонков. Похоже, что первый вызов на самом деле занимает значительное количество времени, а последующие вызовы намного быстрее. Но все же, 25 тиков - это в среднем.

Однако мы с коллегой заметили, что запуск DateTime.UtcNow занимает значительно меньше времени - в среднем всего 0,03 микросекунды.

Учитывая, что наше приложение никогда не будет работать, пока меняется летнее время , я предложил создать следующий класс:

public static class FastDateTime {
    public static TimeSpan LocalUtcOffset { get; private set; }

    public static DateTime Now {
        get { return DateTime.UtcNow + LocalUtcOffset; }
    }

    static FastDateTime() {
        LocalUtcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
    }
}

Другими словами, определите смещение UTC для местного часового пояса один раз - при запуске - и с этого момента используйте скорость DateTime.UtcNow чтобы получить текущее время намного быстрее с помощью FastDateTime.Now.

Я мог видеть, что это проблема, если смещение UTC изменилось во время работы приложения (например, если приложение работало в течение ночи); но, как я уже говорил, в нашем случае этого не произойдет.

У моего коллеги другое представление о том, как это сделать, что мне слишком сложно объяснять здесь. В конечном счете, , насколько я могу судить , оба наших подхода дают точный результат, мой - немного быстрее (~ 0,07 мкс против ~ 0,21 мкс).

То, что я хочу знать, это:

  1. Я что-то здесь упускаю? Учитывая вышеупомянутый факт, что приложение будет работать только в течение периода времени от одной даты, безопасно ли FastDateTime.Now?
  2. Может ли кто-нибудь еще подумать о том, чтобы быстрее узнать текущее время?
24 голоса | спросил 3 revs, 3 users 100%
Dan Tao
1 Jam1000000amThu, 01 Jan 1970 03:00:00 +030070 1970, 03:00:00

4 ответа


0

Не могли бы вы просто использовать DateTime.UtcNow и конвертировать в местное время только при представлении данных? Вы уже определили, что DateTime.UtcNow намного быстрее, и это устранит любую неопределенность вокруг DST.

ответил tjsmith 24 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowSat, 24 Sep 2016 22:41:20 +0300 2016, 22:41:20
0

Одно различие между результатом

DateTime.Now

и

DateTime.UtcNow + LocalUtcOffset 

- это значение свойства Kind - Local против Utc соответственно. Если полученный DateTime передается в стороннюю библиотеку, рассмотрите возможность возврата

DateTime.SpecifyKind(DateTime.UtcNow + LocalUtcOffset, DateTimeKind.Local)
ответил tjsmith 24 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowSat, 24 Sep 2016 22:41:20 +0300 2016, 22:41:20
0

Мне нравится ваше решение. Я сделал несколько тестов, чтобы увидеть, насколько быстрее это по сравнению с обычным DateTime.Now

DateTime.UtcNow в 117 раз быстрее, чем DateTime.Now

использование DateTime.UtcNow достаточно, если нас интересует только продолжительность, а не само время. Если все, что нам нужно, - это рассчитать продолжительность определенного фрагмента кода (выполнить duration= End_time - Start_time), тогда часовой пояс не важен и DateTime.UtcNow достаточно.

Но если нам нужно само время, то нам нужно сделать DateTime.UtcNow + LocalUtcOffset

Просто добавление промежутка времени немного замедляется и теперь, согласно моим тестам, мы всего в 49 раз быстрее, чем обычные DateTime.Now

Если мы поместим это вычисление в отдельную функцию /класс, как предложено, то вызов метода замедлит нас еще больше и мы только в 34 раза быстрее.

Но даже в 34 раза быстрее, это много !!!

Короче говоря, Использование DateTime.UtcNow намного быстрее, чем DateTime.Now

Единственный способ улучшить предложенный класс - это использовать встроенный код: DateTime.UtcNow + LocalUtcOffset вместо вызова метода класса

Кстати, пытаясь заставить компилятор компилировать как встроенный, используя [MethodImpl(MethodImplOptions.AggressiveInlining)] не похоже, чтобы ускорить процесс.

ответил tjsmith 24 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowSat, 24 Sep 2016 22:41:20 +0300 2016, 22:41:20
0

Чтобы ответить в обратном порядке:

2) Я не могу придумать более быстрый путь.

1) Стоит проверить, есть ли какие-либо улучшения в конвейере, как они есть только что объявлено для System.IO

Трудно быть уверенным в безопасности, но это то, что требует многих модульных тестов. Летнее время приходит на ум. Система 1, очевидно, очень боеспособна, а ваша нет.

ответил tjsmith 24 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowSat, 24 Sep 2016 22:41:20 +0300 2016, 22:41:20

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132