Domanda

Vorrei sapere qual è il modo ottimale di memorizzare un certo tipo di dati comune che non sono stati inclusi nella lista sostenuta da buffer di protocollo.

  • datetime (secondi precisione)
  • datetime (millisecondi di precisione)
  • decimali con precisione fissa
  • decimali con una precisione variabile
  • un sacco di valori bool (se hai un sacco di loro sembra che avrete 1-2 byte overhead per ciascuno di essi a causa della loro tag.

Anche l'idea è quella di mappare loro molto facile da corrispondenti / tipi di dati C ++ Python / Java.

È stato utile?

Soluzione

Il design razionale protobuf è più probabile che per mantenere il supporto tipo di dati come "nativo" il più possibile, in modo che sia facile da adottare nuove lingue in futuro. Suppongo che potrebbero fornire in-costruire tipi di messaggio, ma dove si disegna la linea?

La mia soluzione era quella di creare due tipi di messaggi:

DateTime
TimeSpan

Questo è solo perché vengo da un background C #, in cui vengono prese queste tipologie per scontato.

In retrospettiva, TimeSpan e DateTime potrebbe essere stato eccessivo, ma era un modo "economico" di evitare conversione da h / m / s per s e viceversa; Detto questo, sarebbe stato semplice da implementare solo una funzione di utilità come:

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

Bklyn, ha sottolineato che la memoria heap viene utilizzato per i messaggi annidati; in alcuni casi questo è chiaramente molto valida - dobbiamo sempre essere consapevoli di come si usa la memoria. Ma, in altri casi questo può essere di meno preoccupazione, in cui siamo preoccupati di più su facilità di implementazione (questo è il # filosofia Java / C suppongo).

C'è anche un piccolo svantaggio di utilizzare tipi non intrinseci con l'TextFormat::Printer protobuf; non è possibile specificare il formato in cui viene visualizzata, in modo che sarà simile a:

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

... che è troppo prolisso per alcuni. Detto questo, sarebbe più difficile da leggere se fosse rappresentato in secondi.

Per concludere , direi:

  • Se siete preoccupati per la memoria / efficienza parsing, uso secondi / millisecondi.
  • Tuttavia, se la facilità di implementazione è l'obiettivo, utilizzare i messaggi annidati (DateTime, ecc).

Altri suggerimenti

Ecco alcune idee basate sulla mia esperienza con un protocollo simile a filo buffer protocollo.

  

datetime (secondi precisione)

     

datetime (millisecondi precisione)

Penso che la risposta a questi due sarebbe stato lo stesso, si sarebbe solo tipicamente avere a che fare con una gamma più ridotta di numeri nel caso di secondi di precisione.

Usa un sint64 / sfixed64 per memorizzare l'offset in secondi / millisecondi da qualche epoca noto come mezzanotte GMT 1/1/1970. Questo how oggetti Date sono internamente rappresentato in Java . Sono sicuro che ci sono analoghi in Python e C ++.

Se avete bisogno di informazioni sul fuso orario, passare intorno la data / orari in termini di UTC e modellare il fuso orario pertinente come un campo di stringa separata. Per questo, è possibile utilizzare gli identificatori dalla Olson zoneinfo banca dati dal momento che è diventato un po ' standard.

In questo modo si ha una rappresentazione canonica per data / ora, ma si può anche localizzare a qualsiasi fuso orario è pertinente.

  

decimali con precisione fissa

Il mio primo pensiero è quello di utilizzare una stringa simile a come si costruisce oggetti decimale da pacchetto decimale di Python. Suppongo che potrebbe essere inefficiente rispetto a qualche rappresentazione numerica.

Ci possono essere soluzioni migliori a seconda di quale dominio si sta lavorando. Ad esempio, se si sta modellando un valore monetario, forse si può ottenere via con l'utilizzo di un Uint32 / 64 per comunicare il valore in centesimi rispetto agli importi in dollari frazionari.

Ci sono anche alcuni suggerimenti utili a questo thread .

  

decimali con una precisione variabile

non buffer protocollo già supportano questo con galleggiante / doppio tipi scalari? Forse ho frainteso questo punto dell'elenco.

In ogni caso, se si ha la necessità di andare in giro quei tipi scalari, è possibile codificare utilizzando IEEE-754 a Uint32 o uint64 (float rispettivamente vs doppio). Ad esempio, Java permette di estrarre l'IEEE-754 rappresentazione e viceversa da Float / oggetti doppi. Esistono meccanismi analoghi in C ++ / Python.

  

un sacco di valori bool (se hai un sacco   di loro sembra che avrete 1-2   byte overhead per ciascuno di loro a causa di   loro tag.

Se siete preoccupati byte sprecati sul filo, si potrebbe usare tecniche bit-mascheramento per comprimere molti booleani in un singolo Uint32 o uint64.

Perché non c'è il supporto di prima classe nel buffer protocollo, tutte queste tecniche richiedono un po 'di contratto di un gentlemen tra gli agenti. Forse usando una convenzione di denominazione sui vostri campi come "_dttm" o "_mask" aiuterebbe comunicare quando un dato campo ha la semantica di codifica aggiuntivi sopra e al di là del comportamento predefinito di buffer protocollo.

Siamo spiacenti, non è una risposta completa, ma un "me too".

Credo che questa sia una grande domanda, uno mi piacerebbe una risposta a me stesso. L'incapacità di descrivere in modo nativo i tipi fondamentali come datetimes e (per le applicazioni finanziarie) decimali di punto fisso, o MAP loro di lingua specificate o tipi definiti dall'utente è un vero killer per me. La sua più o meno mi ha impedito di essere in grado di utilizzare la libreria, che io altrimenti penso che è fantastico.

Dichiarare il proprio messaggio "DateTime" o "PUNTOFISSO" nella grammatica proto in realtà non è una soluzione, perché è ancora necessario per convertire la rappresentazione della vostra piattaforma da / per gli oggetti generati manualmente, che è soggetto a errori. Inoltre, questi messaggi nidificati vengono memorizzati come puntatori a oggetti mucchio assegnata in C ++, che è selvaggiamente inefficiente quando il tipo sottostante è fondamentalmente solo un intero a 64 bit.

In particolare, vorrei essere in grado di scrivere qualcosa del genere nei miei file proto:

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

E mi sarebbe tenuto a fornire qualsiasi colla era necessario convertire questi tipi da / per fixed64 e Int64 in modo che la serializzazione avrebbe funzionato. Forse attraverso qualcosa di simile a adobe :: promuovere ?

Per datetime con risoluzione di millisecondo ho usato un int64 che ha il datetime come YYYYMMDDHHMMSSmmm. Questo lo rende sia conciso e leggibile, e sorprendentemente, durerà un tempo molto lungo.

Per decimali, ho usato byte[], sapendo che non c'è migliore rappresentazione che non sarà perdita di dati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top