In che modo protobuf-net raggiunge prestazioni rispettabili?
-
19-09-2019 - |
Domanda
Voglio capire perché la soluzione di buffer di protocollo per .NET sviluppato da Marc Gravel è veloce quanto lo è.
Posso capire come la soluzione Google originale abbia raggiunto le sue prestazioni:pregenera codice ottimizzato per la serializzazione degli oggetti;Ho scritto alcune serializzazioni a mano e so che è possibile scrivere codice abbastanza veloce in questo modo se si evita la riflessione.Ma la libreria di Marc è una soluzione runtime che utilizza attributi e non produce alcun codice generato.Quindi, come funziona ?
Soluzione
protobuf-net utilizza un modello strategico;secondo necessità (una sola volta per tipo) utilizza la riflessione per esaminare i tipi e crea un set di serializzatori (basati su un'interfaccia comune) che può utilizzare per serializzare e deserializzare, quindi quando è in uso sta semplicemente attraversando l'insieme noto di serializzatori.
Dentro che cerca di fare un uso sensato della riflessione quando parla con i membri;utilizza Delegate.CreateDelegate
parlare con le proprietà e DynamicMethod
(e IL personalizzato) per parlare con i campi (quando possibile;dipende dal framework di destinazione).Ciò significa che parla sempre conosciuto tipi di delegati, anziché solo DynamicInvoke
(che è molto lento).
Senza impazzire, il codice presenta alcune ottimizzazioni (probabilmente a scapito della leggibilità) in termini di:
- Locale
byte[]
buffering (dei flussi di input/output) - utilizzando array di dimensione fissa (piuttosto che elenchi, ecc.);forse troppo
- usare farmaci generici per evitare la boxe
- numerose modifiche/modifiche/ecc. attorno ai cicli di elaborazione binaria
Col senno di poi, penso di aver commesso un errore sul punto dei generici;la complessità ha comportato l’introduzione forzata dei farmaci generici nel sistema l'ha piegato in alcuni punti, e causa attivamente alcuni grossi problemi (per modelli complessi) su quadro compatto.
Ho alcuni progetti (solo nella mia testa) per rifattorizzarlo utilizzando non-interfacce generiche e invece (per framework idonei) farne un maggiore utilizzo ILGenerator
(la mia prima scelta sarebbe stata Expression
, ma ciò impone una versione del framework più elevata).Il problema, tuttavia, è che ci vorrà molto tempo prima che funzioni, e fino a tempi molto recenti Sono stato piuttosto sommerso.
Recentemente ci sono riuscito ricominciare a passare un po' di tempo su protobuf-net, quindi spero di eliminare il mio arretrato di richieste ecc. e di iniziare presto.È anche mia intenzione farlo funzionare con i modelli altro rispetto alla riflessione (ad es.descrivendo separatamente la mappatura dei cavi).
e non produce alcun codice generato
Dovrei anche chiarire che ci sono due percorsi di codegen (facoltativi) se si desidera utilizzare il codice generato;protogen.exe o il Componente aggiuntivo VS, consentono la generazione di codice da un file .proto.Ma non è così necessario - è utile principalmente se si dispone di un file .proto esistente o si intende interagire con un altro linguaggio (C++ ecc.) per lo sviluppo basato sul contratto.
Altri suggerimenti
La sua performance molto buona!
Si può vedere un confronto completo tra diversi formati tra cui protobuf fatto da me- http : //maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/
Questo confronto comprende campioni grandi e piccoli di dati e formati diversi.
Una delle prove della mia post-