Подтвердить что ты не робот

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

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

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

  • Я иногда подозреваю, что те люди, которые всегда говорят: "Компьютеры бывают быстрыми, читаемость всегда приходит перед оптимизацией" часто говорят из опыта разработки приложений, где производительность, хотя это может быть важно, не является критическим, Я говорю о необходимости того, чтобы все происходило как можно ближе к мгновенному - например, в течение наносекунд (в некоторых отраслях это имеет значение, например, в режиме высокой частоты в реальном времени).
  • Даже учитывая это, альтернативный подход, который я опишу ниже, на самом деле вполне читабельен. Это не странный взлом, просто простой метод, который работает надежно и быстро.
  • У нас есть тесты. 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 микросекунды).

Что я хочу знать:

  • Мне что-то не хватает? Учитывая вышеупомянутый факт, что приложение будет работать только в пределах периода одной даты, FastDateTime.Now безопасно?
  • Может ли кто-нибудь еще подумать о еще более быстром способе получения текущего времени?
4b9b3361

Ответ 1

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

Ответ 2

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

DateTime.Now

и

DateTime.UtcNow + LocalUtcOffset 

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

DateTime.SpecifyKind(DateTime.UtcNow + LocalUtcOffset, DateTimeKind.Local)

Ответ 3

Мне нравится ваше решение. Я сделал несколько тестов, чтобы увидеть, насколько быстрее он сравнивается с обычным 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 вместо вызова метода класса

BTW пытается заставить компилятор компилироваться как встроенный с помощью [MethodImpl(MethodImplOptions.AggressiveInlining)] казалось, не ускоряли ход событий.

Ответ 4

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

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

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

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