2009-05-07 8 views
7

Potrzebuję serializować wartość .NET DateTime w komunikacie o buforach protokołów.Bufory protokołów: Czy powinienem używać int64 lub fixed64 do reprezentowania wartości .NET DateTime?

Mój plan polega na użyciu funkcji DateTime.ToBinary(), a następnie przesłaniu 64-bitowej wartości zwracanej w wiadomości. Ale nie jestem pewien, co wybrać jako bufor buforuje typ danych do reprezentowania tego.

Domyślam się, że jestem zakłopotany o , kiedy należy użyć typów danych fixed64 (lub sfixed64).

Zakładam, że w tym scenariuszu użyłbym podpisanych typów, ponieważ wartości zwracane przez DateTime.ToBinary() mogą być zarówno ujemne, jak i dodatnie.

+0

Osobiście wątpię w mądrość ToBinary w pierwszej kolejności - zobacz odpowiedź na więcej. –

Odpowiedz

9

Cóż, na pewno chcesz albo int64 lub sfixed64 poradzić sobie z wartością, która jest podpisana.

Po przeprowadzeniu szybkiego testu, DateTime.Now.ToBinary() jest zakodowany w 10 bajtach przy użyciu int64, podczas gdy sfixed64 zawsze używa 8 bajtów. Zasadniczo kodowanie o zmiennej długości jest świetne dla małych liczb, ale staje się większe niż ustalone kodowanie dużych liczb. (Jest to ten sam rodzaj kompromisu co użycie UTF-8 zamiast UTF-16 - znaki ASCII mogą być kodowane w UTF-8 w jednym bajcie, ale później punkty kodowe kończą się zakodowanymi jako 2, a następnie 3 bajtami, podczas gdy UTF -16 zawsze wykorzystuje 2 bajty dla znaków w formacie BMP).

Domyślam się, że DateTime.ToBinary() wartości prawdopodobne być dość duże (nie znając szczegółów dokładnie co robi), więc sfixed64 jest bardziej odpowiednie.

Czy to ma sens?

+1

Więc w zasadzie sfixed64 jest lepiej dopasowany w tym przypadku, ponieważ używa on kodowania o stałej długości w porównaniu do sint64, który ma zmienną długość i dlatego nadaje się do mniejszych wartości. Czy mam rację? –

+1

Tak, dokładnie tak. –

+1

'ToBinary()' zwykle koduje jako 10 bajtów, ponieważ górne 2 bity wartości 'int64' to' Kind'. Ale wartość 'Ticks' _ może_ wynosić 62 bity. Jeśli nie potrzebujesz ziarnistości wynoszącej 100 nanosekund, wówczas 'now.Ticks/TimeSpan.TickPerSecond' (lub inna dowolna ziarnistość, której potrzebujesz) przekazane do proto jako' int64' będzie najkrótszym bajtem [], ale jeśli nie zrobisz tego jako @ MarcGravell sugeruje, obie strony muszą znać dzielnik. –

0

Należy użyć podpisane liczbę 64-bitową, a nie dlatego, że DateTime może być ujemny, ale ponieważ metoda ToBinary zwraca Int64, który jest podpisany liczbę 64-bitową.

+1

Dzięki za odpowiedź Guffa, ale to tak naprawdę nie odpowiada na moje pytanie. Interesuje mnie, czy w tym przypadku należy używać typów danych "fixed64". Z wyjaśnieniem, dlaczego to możliwe! –

4

W protobuf-net używam stopniową skalę podejście (i rzeczywiście, to zajmuje to wszystko dla Ciebie, jeśli po prostu użyć DateTime) - odpowiednik .proto jest coś takiego:

message DateTime { 
    optional sint64 value = 1; // the offset (in units of the selected scale) 
          // from 1970/01/01 
    optional TimeSpanScale scale = 2 [default = DAYS]; // the scale of the 
                // timespan 
    enum TimeSpanScale { 
    DAYS = 0; 
    HOURS = 1; 
    MINUTES = 2; 
    SECONDS = 3; 
    MILLISECONDS = 4; 

    MINMAX = 15; // dubious 
    } 
} 

czyli jeśli DateTime można wyrazić w całych dniach, po prostu wysyłam liczbę dni od 1970, itd. - plus mały znacznik do skali. Oznacza to, że daty mogą być wysyłane nieco bardziej efektywnie, ale nie kosztuje to o wiele więcej w przypadku innych skal.

Osobiście nie użyłbym ToBinary() - użyłbym wyraźnie przesunięcia o znanej skali od znanej epoki (takiej jak epoki unix). Dzięki temu jest bardziej przenośny między platformami. Ale jeśli wysyłasz (na przykład) tylko przesunięcie milisekundy, stała skala będzie zazwyczaj bardziej wydajna niż skala o długości wariantowej. To, czy potrzebujesz podpisu czy podpisu, zależy od tego, czy potrzebujesz dat przed epoką ;-p

+0

Marc, dziękuję za wgląd. W rzeczywistości już przeniosłem się do podejścia bardzo podobnego do twojego (używając epoki Linux-a), ale wciąż byłem ciekawy co do prawidłowego użycia buforów protokołów fix64/sfixed64. Wydaje mi się, że można powiedzieć, że moje pytanie było nieco akademickie, ponieważ naprawdę interesowałem się stosowaniem różnych typów dostępnych do kodowania danych za pomocą buforów protokołów. –

Powiązane problemy