Kolega i ja poruszamy się w tej sprawie i mam nadzieję uzyskać opinie zewnętrzne na temat tego, czy moje proponowane rozwiązanie jest dobrym pomysłem, czy nie.Optymalizowanie alternatywy dla DateTime.Now
Po pierwsze, zrzeczenie się: zdaję sobie sprawę, że pojęcie "optymalizacji DateTime.Now
" dla niektórych z was jest szalone. Mam parę obrony poboru:
- Czasami podejrzewam, że ci ludzie, którzy zawsze mówią: „Komputery są szybkie, czytelność zawsze przychodzi przed optymalizacją” są często mówiąc z doświadczenia tworzenia aplikacji gdzie wydajność, choć może to być ważne, nie jest krytyczne. Mówię o tym, że rzeczy muszą się wydarzyć tak blisko, jak to tylko możliwe - w ciągu nanosekund (w niektórych branżach ta sprawa dotyczy np. Handlu w czasie rzeczywistym z wysoką częstotliwością).
- Mając to na uwadze, alternatywne podejście, które opisuję poniżej, jest w rzeczywistości dość czytelne. To nie jest dziwaczny hack, tylko prosta metoda, która działa niezawodnie i szybko.
- Mamy mają prowadzi testy.
DateTime.Now
is slow (relatywnie rzecz biorąc). Metoda poniżej jest szybsza o.
Teraz, na samo pytanie.
Zasadniczo z testów odkryliśmy, że uruchomienie DateTime.Now
zajmuje około 25 tików (około 2,5 mikrosekundy). Jest to średnio uśrednione na tysiące do milionów połączeń. Wygląda na to, że pierwsze połączenie zajmuje naprawdę dużo czasu, a kolejne połączenia są znacznie szybsze. Ale nadal 25 kleszczy jest średnią.
Jednakże, mój współpracownik i ja zauważyliśmy, że DateTime.UtcNow
zajmuje znacznie mniej czasu do uruchomienia - średnio zaledwie 0,03 mikrosekundy.
Biorąc pod uwagę, że nasza aplikacja nie będzie działać, gdy nastąpiła zmiana w czas letni, moja sugestia było stworzenie następujące klasy:
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);
}
}
Innymi słowy, określić przesunięcie UTC dla lokalna strefa czasowa raz - przy starcie - i od tego momentu wykorzystaj prędkość DateTime.UtcNow
, aby uzyskać bieżący czas o wiele szybciej poprzez FastDateTime.Now
.
Mogłem zobaczyć, że jest to problem, jeśli przesunięcie UTC uległo zmianie w czasie działania aplikacji (jeśli na przykład aplikacja działała przez noc); ale jak już wspomniałem, w naszej sprawie tak się nie stanie.
Mój kolega ma inny pomysł na temat tego, jak to zrobić, co jest nieco zbyt zaangażowane, aby mi to wyjaśnić. Ostatecznie, o ile mogę powiedzieć, oba nasze podejścia zwracają dokładny wynik, mój jest nieco szybszy (~ 0.07 mikrosekund vs. ~ 0.21 mikrosekund).
Co chcę wiedzieć:
- Am I brakuje czegoś tutaj? Biorąc pod uwagę powyższy fakt, że aplikacja będzie działała tylko w ramach czasowych jednej daty, czy jest ona bezpieczna?
- Czy ktoś inny może pomyśleć o nawet szybszym sposobie uzyskania aktualnego czasu?
Przejście DST jest zwykłym niedopatrzymaniem przy wprowadzaniu tego typu uproszczeń, a już wcześniej zastrzegłeś, że to nie będzie problemem. Łapie ludzi na baczność, aby odkryć, że oni (i ich oprogramowanie użytkowe) żyją w 2 strefach czasowych, bez przesuwania się o cal. I jest to podwójnie trudne, że jedyny moment, w którym twój pakiet testowy go przechwytuje, jest taki, że zdarza się, że działa podczas przejścia DST, co jest rzadkim zjawiskiem w najlepszym przypadku (lub jest wyśmiewany w ramach zestawu testów, który, jak twierdzę, jest równomierny rzadsze rzeczy). – PaulMcG