2009-03-15 20 views
44

Per alcuni caching che sto pensando di fare per un progetto imminente, ho pensato alla serializzazione Java. Vale a dire, dovrebbe essere usato?Serializzazione ad alte prestazioni: Java vs Google Protocol Buffers vs ...?

Ora ho scritto in precedenza serializzazione personalizzata e deserializzazione (Externalizable) per vari motivi negli anni passati. Oggigiorno l'interoperabilità è diventata ancora più problematica e posso prevedere la necessità di interagire con le applicazioni .Net, quindi ho pensato di utilizzare una soluzione indipendente dalla piattaforma.

Qualcuno ha avuto esperienza con l'utilizzo ad alte prestazioni di GPB? Come si confronta in termini di velocità ed efficienza con la serializzazione nativa di Java? In alternativa, ci sono altri schemi da prendere in considerazione?

+0

Confronto di prestazioni completo di diversi formati di serializzazione - http://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/ – Maxim

+0

so questa è una vecchia domanda, ma esiste un progetto Benchmark https://github.com/eishay/jvm-serializers/wiki dedicato alla serializzazione java. – kromit

risposta

55

Non ho confrontato i buffer di protocollo con la serializzazione nativa di Java in termini di velocità, ma per l'interoperabilità la serializzazione nativa di Java è un no-no serio. Inoltre, nella maggior parte dei casi non sarà altrettanto efficiente in termini di spazio come buffer di protocollo. Certo, è un po 'più flessibile in termini di ciò che può memorizzare, e in termini di riferimenti ecc. Il protocollo Buffer è molto buono per quello a cui è destinato e quando soddisfa le tue necessità è fantastico - ma ci sono ovvie restrizioni dovute all'interoperabilità (e altre cose).

Recentemente ho pubblicato un framework di benchmarking di Protocol Buffers in Java e .NET. La versione Java è nello main Google project (nello), la versione .NET è my C# port project. Se si desidera confrontare la velocità PB con la velocità di serializzazione Java, è possibile scrivere classi simili e confrontarle. Se sei interessato all'interop, però, non darei seriamente la serializzazione Java nativa (o la serializzazione binaria nativa .NET).

Non ci sono altre opzioni per la serializzazione interoperabili oltre buffer protocollo però - Thrift, JSON e YAML vengono in mente, e ci sono senza dubbio gli altri.

MODIFICA: Va bene, se l'interoperabilità non è così importante, vale la pena cercare di elencare le diverse qualità che si desidera da un framework di serializzazione. Una cosa che dovresti pensare è il controllo delle versioni - questa è un'altra cosa che PB è progettata per gestire bene, sia a ritroso che a termine (quindi il nuovo software può leggere i vecchi dati e viceversa) - quando ti attieni alle regole suggerite, ovviamente :)

Avendo provato a essere cauto riguardo la serializzazione Java performance vs nativa, non sarei davvero sorpreso di scoprire che PB era comunque più veloce. Se si ha la possibilità, utilizzare il server VM: i miei benchmark recenti hanno mostrato che la VM del server è con una velocità doppia rispetto a durante la serializzazione e la deserializzazione dei dati di esempio. Penso che il codice PB si adatti molto bene al JIT del server VM :)

Proprio come le cifre di esempio, serializzando e deserializzando due messaggi (uno 228 byte, un 84750 byte) ho ottenuto questi risultati sul mio portatile usando il server VM:

 
Benchmarking benchmarks.GoogleSize$SizeMessage1 with file google_message1.dat 
Serialize to byte string: 2581851 iterations in 30.16s; 18.613789MB/s 
Serialize to byte array: 2583547 iterations in 29.842s; 18.824497MB/s 
Serialize to memory stream: 2210320 iterations in 30.125s; 15.953759MB/s 
Deserialize from byte string: 3356517 iterations in 30.088s; 24.256632MB/s 
Deserialize from byte array: 3356517 iterations in 29.958s; 24.361889MB/s 
Deserialize from memory stream: 2618821 iterations in 29.821s; 19.094952MB/s 

Benchmarking benchmarks.GoogleSpeed$SpeedMessage1 with file google_message1.dat 
Serialize to byte string: 17068518 iterations in 29.978s; 123.802124MB/s 
Serialize to byte array: 17520066 iterations in 30.043s; 126.802376MB/s 
Serialize to memory stream: 7736665 iterations in 30.076s; 55.93307MB/s 
Deserialize from byte string: 16123669 iterations in 30.073s; 116.57947MB/s 
Deserialize from byte array: 16082453 iterations in 30.109s; 116.14243MB/s 
Deserialize from memory stream: 7496968 iterations in 30.03s; 54.283176MB/s 

Benchmarking benchmarks.GoogleSize$SizeMessage2 with file google_message2.dat 
Serialize to byte string: 6266 iterations in 30.034s; 16.826494MB/s 
Serialize to byte array: 6246 iterations in 30.027s; 16.776697MB/s 
Serialize to memory stream: 6042 iterations in 29.916s; 16.288969MB/s 
Deserialize from byte string: 4675 iterations in 29.819s; 12.644595MB/s 
Deserialize from byte array: 4694 iterations in 30.093s; 12.580387MB/s 
Deserialize from memory stream: 4544 iterations in 29.579s; 12.389998MB/s 

Benchmarking benchmarks.GoogleSpeed$SpeedMessage2 with file google_message2.dat 
Serialize to byte string: 39562 iterations in 30.055s; 106.16416MB/s 
Serialize to byte array: 39715 iterations in 30.178s; 106.14035MB/s 
Serialize to memory stream: 34161 iterations in 30.032s; 91.74085MB/s 
Deserialize from byte string: 36934 iterations in 29.794s; 99.98019MB/s 
Deserialize from byte array: 37191 iterations in 29.915s; 100.26867MB/s 
Deserialize from memory stream: 36237 iterations in 29.846s; 97.92251MB/s 

La "velocità" rispetto a "dimensione" indica se il codice generato è ottimizzato per la velocità o la dimensione del codice. (I dati serializzati sono gli stessi in entrambi i casi. La versione "size" è fornita per il caso in cui hai molti messaggi definiti e non vuoi prendere molta memoria per il codice.)

Come si può vedere, per il messaggio più piccolo può essere molto veloce - oltre 500 piccoli messaggi serializzati o deserializzati per millisecondo. Anche con il messaggio 87K ci vuole meno di un millisecondo per messaggio.

+0

Devo sottolineare che l'interoperabilità .Net non è un requisito chiave. L'organizzazione è al 100% Java, ma il progetto avrà una vita di almeno 5 anni, quindi sto solo pensando al futuro. – cletus

+0

Potresti fornire un link al tuo benchmark framework? –

+0

Link aggiunto nel testo: in pratica http://code.google.com/p/protobuf/source/browse/#svn/trunk/benchmarks –

5

Cosa intendete per alte prestazioni? Se si desidera la serializzazione milli-secondo, suggerisco di utilizzare l'approccio di serializzazione che è il più semplice. Se si desidera sub milli-secondo è probabile che sia necessario un formato binario. Se si desidera molto meno di 10 micro secondi, è probabile che sia necessaria una serializzazione personalizzata.

Non ho visto molti benchmark per la serializzazione/deserializzazione ma pochi supportano meno di 200 micro-secondi per la serializzazione/deserializzazione.

I formati indipendenti dalla piattaforma hanno un costo (in termini di sforzo da parte dell'utente e latenza), potrebbe essere necessario decidere se si desidera ottenere prestazioni o indipendenza dalla piattaforma. Tuttavia, non vi è alcun motivo per cui non sia possibile avere entrambe le opzioni di configurazione che vengono alternate come richiesto.

+0

Si parla di "pochi supporti inferiori a 200 micro secondi". Puoi dire a chi pensi? –

+0

La serializzazione Java è già "un formato binario". Direi anche che le misurazioni esatte in assenza di sapere cosa viene serializzato (e il computer su cui è in esecuzione) sono praticamente inutili. Il throughput di serializzazione/deserializzazione è una misura più significativa, ma è ancora dipendente dal computer. –

+2

Vedere i miei benchmark per esempi di serializzazione o deserializzazione di un * piccolo * messaggio in meno di * 2 * microsecondi :) –

1

Ecco il largo la suggestione muro della giornata :-) (basta ottimizzato qualcosa nella mia testa che io ora voglio provare) ...

Se si può andare per l'intera soluzione di caching tramite questo potrebbe funzionare: Project Darkstar. È progettato come server di gioco ad altissime prestazioni, in modo specifico che le letture siano veloci (così buone per una cache). Ha API Java e C, quindi credo (pensavo che fosse passato molto tempo da quando l'ho guardato, e non pensavo a questo poi) che tu potessi salvare oggetti con Java e leggerli di nuovo in C e viceversa.

Se non altro ti darà qualcosa da leggere su oggi :-)

6

Se stai confondendo tra PB & nativo serializzazione java sulla velocità e l'efficienza, basta andare per PB.

  • PB è stato progettato per raggiungere tali fattori. Vedi http://code.google.com/apis/protocolbuffers/docs/overview.html
  • I dati PB sono molto piccoli mentre la serializzazione java tende a replicare un intero oggetto, inclusa la sua firma. Perché ottengo sempre il nome della mia classe, il nome del campo ... serializzato, anche se lo conosco interiormente al destinatario?
  • Pensa allo sviluppo linguistico. Sta diventando difficile se una parte usa Java, una parte usa il C++ ...

Alcuni sviluppatori suggeriscono Thrift, ma io userei Google PB perché "Credo in google" :-) .. Comunque, vale la pena per uno sguardo: punto http://stuartsierra.com/2008/07/10/thrift-vs-protocol-buffers

14

più uno dei dati: questo progetto:

http://code.google.com/p/thrift-protobuf-compare/

dà un'idea delle prestazioni previste per i piccoli oggetti, tra cui la serializzazione Java su PB.

I risultati variano molto a seconda della piattaforma, ma ci sono alcune tendenze generali.

5

Si potrebbe anche dare un'occhiata a FST, una sostituzione drop-in per la serializzazione JDK integrata che dovrebbe essere più veloce e avere un output più piccolo.

stime prime sul benchmark frequente che ho fatto in questi anni:

100% = binari/approcci basati struct (per esempioSBE, FST-struct)

  • scomodi
  • post-elaborazione (costruire obejcts "reali" a lato del ricevitore) può mangiare fino vantaggi di prestazioni e non è mai compreso nel benchmark

~ 10% -35 % protobuf & Derivati ​​

~ 10% -30% serializzatori veloci come FST e KRYO

  • Gli oggetti convenienti e deserializzati possono essere utilizzati più spesso direttamente senza codice di traduzione manuale aggiuntivo.
  • può essere pimped per performance (annotazioni, classe registrazione)
  • preservare pubblicitari sul grafico oggetto (nessun oggetto serializzato due volte)
  • può gestire strutture cicliche
  • soluzione generica, FST è completamente compatibile con JDK serializzazione

~ 2% -15% JDK serializzazione

~ 1% JSON veloce -15% (ad es Jackson)

  • non può gestire qualsiasi oggetto grafico ma solo un piccolo sottoinsieme di strutture di dati java
  • senza rif ripristino

0.001-1% full grafico JSON/XML (ad esempio JSON.io)

Questi numeri hanno lo scopo di dare un'impressione di ordine di grandezza molto approssimativa. Si noti che le prestazioni dipendono molto dalle strutture di dati serializzate/benchmark. Pertanto, semplici benchmark di classe semplice sono per lo più inutili (ma popolari: ad esempio ignorando unicode, nessuna raccolta, ..).

vedi anche

http://java-is-the-new-c.blogspot.de/2014/12/a-persistent-keyvalue-server-in-40.html

http://java-is-the-new-c.blogspot.de/2013/10/still-using-externalizable-to-get.html

+0

FST ha funzionato alla grande con mapdb. –

0

per la serializzazione filo-friendly, è possibile utilizzare l'interfaccia Externalizable. Se usato in modo intelligente, avrai conoscenze intime per decidere come eseguire il marshalling e l'unmarshall dei campi specifici in modo ottimale. Detto questo, dovrai gestire correttamente il controllo di versione di ogni oggetto: è facile smontare un marshall, ma eseguire nuovamente il marshalling di un oggetto V2 quando il tuo codice supporta V1 interromperà, perderà informazioni o peggiorerà i dati corrotti in un modo in cui le tue app non sono in grado di elaborare correttamente. Se stai cercando un percorso ottimale, fai attenzione a nessuna libreria risolverà il tuo problema senza alcuni compromessi. Generalmente le librerie si adatteranno alla maggior parte dei casi d'uso e avranno l'ulteriore vantaggio che si adatteranno e miglioreranno nel tempo senza il tuo contributo, se hai optato per un progetto open source attivo. E potrebbero aggiungere problemi di prestazioni, introdurre bug e persino correggere bug che non ti hanno ancora colpito!

Problemi correlati