2009-09-30 9 views
7

Chciałbym dowiedzieć się, jaki jest optymalny sposób przechowywania typowych danych, które nie zostały uwzględnione na liście obsługiwanej przez bufory protokołu.Jakie są najlepsze sposoby wykorzystania liczb dziesiętnych i dat za pomocą buforów protokołów?

  • datetime (sekundy precyzja)
  • datetime (milisekund precyzja)
  • dziesiętne ze stałą precyzją
  • dziesiętne o zmiennej precyzji
  • wiele wartości bool (jeśli masz wiele z nich wygląda dla każdego z nich będziesz mieć 1-2 bajty na górze ze względu na znaczniki.

Pomysł jest również bardzo prosty w mapowaniu nding C++/Python/Java typy danych.

Odpowiedz

3

Uzasadnienie projektu protobuf najprawdopodobniej utrzymuje typ danych jako "natywny", tak aby w przyszłości łatwo było adoptować nowe języki. Przypuszczam, że mogliby dostarczyć wbudowane typy wiadomości, ale gdzie narysujesz linię?

Moje rozwiązanie było utworzyć dwa rodzaje wiadomości:

DateTime 
TimeSpan 

to tylko dlatego, że pochodzą z C# tło, gdzie te typy są brane za pewnik.

Z perspektywy czasu, TimeSpan i DateTime mogły być przesadą, ale był to "tani" sposób uniknięcia konwersji z h/m/s na s i odwrotnie; powiedział, że to byłoby proste, po prostu zaimplementować funkcję użytkową, takich jak:

int TimeUtility::ToSeconds(int h, int m, int s) 

Bklyn, zwrócił uwagę, że pamięć sterty służy do zagnieżdżonych wiadomości; w niektórych przypadkach jest to oczywiście bardzo ważne - zawsze powinniśmy być świadomi, jak pamięć jest używana. Ale w innych przypadkach może to być mniej niepokojące, gdzie martwimy się bardziej o łatwość implementacji (jest to filozofia Java/C#, którą przypuszczam).

Istnieje również niewielka wada stosowania nieidentycznych typów z protobufem TextFormat::Printer; nie można określić formatu, w jakim jest wyświetlany, więc będzie wyglądać mniej więcej tak:

my_datetime { 
    seconds: 10 
    minutes: 25 
    hours: 12 
} 

... co dla niektórych jest zbyt szczegółowe. To powiedziawszy, trudniej byłoby odczytać, gdyby był przedstawiony w kilka sekund.

Podsumowując, powiedziałbym:

  • Jeśli martwisz się o pamięć/parsowania efektywności, użyj sekund/milisekund.
  • Jeśli jednak celem jest łatwość implementacji, użyj zagnieżdżonych wiadomości (DateTime itd.).
2

Niestety, nie jest to pełna odpowiedź, ale "ja też".

Myślę, że to jest świetne pytanie, takie, które chciałabym odpowiedzieć sobie. Niezdolność do natywnie opisywania podstawowych typów, takich jak serwery czasu i (dla aplikacji finansowych) stałych miejsc dziesiętnych, lub mapowania ich na typy określone przez użytkownika lub zdefiniowane przez użytkownika, jest dla mnie prawdziwym zabójcą. W mniejszym lub większym stopniu uniemożliwiał mi korzystanie z biblioteki, co według mnie jest fantastyczne.

Zgłaszanie własnego komunikatu "DateTime" lub "FixedPoint" w gramatyce proto nie jest rozwiązaniem, ponieważ nadal trzeba ręcznie konwertować reprezentację platformy na/z wygenerowanych obiektów, co jest podatne na błędy. Ponadto te zagnieżdżone komunikaty są zapisywane jako wskaźniki do obiektów alokowanych na sterty w C++, co jest szalenie nieefektywne, gdy podstawowy typ jest po prostu 64-bitową liczbą całkowitą.

Konkretnie chciałbym, aby móc napisać coś takiego w moich plików proto:

message Something { 
    required fixed64 time = 1 [cpp_type="boost::posix_time::ptime"]; 
    required int64 price = 2 [cpp_type="fixed_point<int64_t, 4>"]; 
    ... 
}; 

I chciałbym być wymagane podanie cokolwiek klej było konieczne w celu przekształcenia tych typów do/z fixed64 i int64, aby serialowanie działało. Może przez coś takiego jak adobe::promote?

3

Oto kilka pomysłów na podstawie mojego doświadczenia z protokołem przewodowym podobnym do buforów protokołów.

datetime (sekundy precyzja)

datetime (milisekund precyzja)

Myślę, że odpowiedź na te dwa byłyby takie same, to po prostu zwykle do czynienia z mniejszym zakresie liczb w przypadku precyzji sekund.

Sint64/sfixed64 służy do przechowywania przesunięcia w sekundach/milisekundach od dobrze znanej epoki, takiej jak północ GMT 1/1/1970. To, jak obiekty Date są internally represented in Java. Jestem pewien, że istnieją analogi w Pythonie i C++.

Jeśli potrzebujesz informacji o strefie czasowej, podaj datę/czas w ujęciu UTC i modeluj odpowiednią strefę czasową jako oddzielne pole tekstowe. W tym celu można użyć identyfikatorów z Olson Zoneinfo database, ponieważ stało się to nieco standardowe.

W ten sposób można uzyskać kanoniczną reprezentację daty/czasu, ale można również zlokalizować w dowolnej strefie czasowej.

dziesiętne ze stałą precyzją

moja pierwsza myśl jest użycie ciąg podobny do tego, jak się konstruuje dziesiętne obiekty z pakietu dziesiętnych Pythona. Przypuszczam, że może to być nieefektywne w stosunku do jakiejś reprezentacji liczbowej.

Możliwe, że istnieją lepsze rozwiązania w zależności od domeny, z którą współpracujesz. Na przykład, jeśli modelujesz wartość pieniężną, być może uda Ci się uciec za pomocą uint32/64, aby przekazać wartość w centach, w przeciwieństwie do ułamkowych kwot w dolarach.

Istnieje również kilka przydatnych sugestii w this thread.

dziesiętne o zmiennej precyzji

Nie Protocol Zderzaki już wspierać ten z pływakiem/podwójnych typów skalarnych? Może źle zrozumiałem tę kwestię.

W każdym razie, jeśli potrzebowałeś obejść te typy skalarne, możesz kodować używając IEEE-754 do uint32 lub uint64 (odpowiednio float vs double). Na przykład Java allows you to extract the IEEE-754 representation i vice versa z obiektów Float/Double. Istnieją analogiczne mechanizmy w C++/Pythonie.

wiele wartości bool (jeśli masz dużo z nich wygląda jak będziesz miał 1-2 bajtów narzutu dla każdego z nich ze względu na ich tagów.

Jeżeli jesteś zaniepokojony marnowaniem bajtów na przewodzie, można użyć bit-masking techniques, aby skompresować wiele booleans w jednym uint32 lub uint64.

Ponieważ nie ma pierwszej klasy wsparcia w buforze protokołów, wszystkie te techniki wymagają trochę dżentelmenów " umowa między agentami . Być może użycie konwencji nazewnictwa na twoich polach, takich jak "_dttm" lub "_mask", pomogłoby komunikować się, gdy dane pole zawiera dodatkową semantykę kodowania wykraczającą poza domyślne zachowanie buforów protokołów.

1

Dla datetime z rozdzielczością milisekund użyłem int64, który ma datę i godzinę jako YYYYMMDDHHMMSSmmm. To sprawia, że ​​jest on zarówno zwięzły i czytelny, jak i zaskakujący, będzie trwał bardzo długo.

Dla ułamków dziesiętnych użyłem byte[], wiedząc, że nie ma lepszej reprezentacji, która nie będzie stratna.

Powiązane problemy