Pergunta

Para alguns cache Estou pensando em fazer para um próximo projeto, eu estive pensando sobre a serialização Java. Ou seja, ele deve ser usado?

Agora eu tenho escrito previamente serialização personalizada e desserialização (Externalizable) por várias razões nos últimos anos. Estes dias interoperabilidade tornou-se ainda mais de um problema e eu posso prever a necessidade de interagir com aplicativos .NET para que eu tenha pensado em usar uma solução de plataforma-independente.

Alguém já teve alguma experiência com uso de GPB de alta performance? Como ele se compara em termos de velocidade e eficiência com serialização nativa de Java? Como alternativa, existem outros esquemas vale a pena considerar?

Foi útil?

Solução

Eu não têm comparado Protocol Buffers com serialização nativa de Java em termos de velocidade, mas para a interoperabilidade de serialização nativa do Java é uma séria falta de nenhum. Ele também não vai ser tão eficiente em termos de espaço como Protocol Buffers na maioria dos casos. Claro, é um pouco mais flexível em termos do que ele pode armazenar, e em termos de referências etc. Protocol Buffers é muito bom no que ele está destinado a, e quando ele se encaixa a sua necessidade é grande - mas há restrições óbvias devido à interoperabilidade (e outras coisas).

Eu afixei recentemente um quadro de benchmarking Protocol Buffers em Java e .NET. A versão Java é na principal projeto Google (no benchmarks diretório ), a versão .NET está em my C # projeto portuário . Se você quiser comparar a velocidade PB com Java velocidade de serialização você poderia escrever classes e referência-los semelhantes. Se você estiver interessado em interoperabilidade, porém, eu realmente não daria serialização Java nativo (ou .NET nativa serialização binária) um segundo pensamento.

Existem outras opções para serialização interoperável além Protocol Buffers embora - Thrift , JSON e YAML vêm à mente, e há outros sem dúvida.

EDIT: Ok, com interoperabilidade não ser tão importante, que vale a pena tentar listar as diferentes qualidades que você quer fora de um quadro de serialização. Uma coisa que você deve pensar é versionamento - isso é outra coisa que PB é projetado para lidar bem, tanto para trás e para a frente (tão novo software pode ler dados antigos e vice-versa) - quando você seguir as regras sugeridas, é claro :)

Depois de ter tentado ser cauteloso sobre o desempenho Java vs serialização nativa, eu realmente não ficaria surpreso ao descobrir que PB foi mais rápido de qualquer maneira. Se você tiver a chance, use o vm servidor - meus benchmarks recentes mostraram o servidor VM para ser duas vezes mais rápido na serialização e desserialização os dados de exemplo. Eu acho que os ternos de código PB JIT o servidor da VM muito bem:)

Assim como figuras de desempenho de amostra, serialização e desserialização duas mensagens (uma 228 bytes, um 84750 bytes) Eu tenho esses resultados no meu laptop, usando o servidor 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 

A "velocidade" vs "tamanho" é se o código gerado é otimizado para velocidade ou tamanho do código. (Os dados serializados é a mesma em ambos os casos. A versão "tamanho" é fornecido para o caso em que você tem um monte de mensagens definidas e não quer ter um monte de memória para o código.)

Como você pode ver, para a mensagem menor pode ser muito rápido - mais de 500 mensagens pequenas serializado ou desserializado por milissegundo . Mesmo com a 87K mensagem está levando menos de um milissegundo por mensagem.

Outras dicas

Um ponto mais dados: este projeto:

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

dá uma idéia do desempenho esperado para pequenos objetos, incluindo serialização Java em PB.

Os resultados variam muito dependendo da sua plataforma, mas existem algumas tendências gerais.

Você também pode ter um olhar para FST , um substituto para incorporado no JDK serialização que deve ser mais rápido e tem saída menor.

estimativas matérias sobre a freqüente avaliação comparativa que tenho feito nos últimos anos:

100% = Binário / struct abordagens com base (por exemplo, SBE, FST-estruturas)

  • inconveniente
  • pós-processamento (acumulação obejcts "reais" no lado receptor) pode comer-se vantagens de desempenho e nunca é incluído no benchmarks

~ 10% -35% protobuf e derivados

~ 10% -30% serializers rápidas, como FST e KRYO

  • convenientes, objetos desserializados pode ser usado na maioria das vezes diretamente, sem código de tradução manual adicional.
  • pode ser pimped para o desempenho (anotações, classe registrar)
  • preservar ligações em gráfico objecto (nenhum objecto em série duas vezes)
  • pode lidar com estruturas cíclicas
  • solução genérica, FST é compatível com JDK serialização

~ 2% -15% JDK serialização

~ 1% -15% rápido JSon (por exemplo Jackson)

  • não pode lidar com qualquer objecto gráfico, mas apenas um pequeno subconjunto de estruturas de dados Java
  • não ref restauração

0,001-1% gráfico completo JSon / XML (por exemplo JSON.io)

Estes números servem para dar uma impressão muito áspera ordem de grandeza. Note-se que o desempenho depende muito das estruturas de dados que está sendo serializado / aferido. Então benchmarks classe única e simples são praticamente inúteis (mas popular: por exemplo, ignorando unicode, há coleções, ..).

ver também

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

Se você está confuso entre PB & serialização java nativo em velocidade e eficiência, basta ir para PB.

  • PB foi projetado para atingir tais fatores. Consulte http://code.google.com/apis/protocolbuffers/docs/overview. html
  • dados
  • PB é muito pequeno, enquanto java serialização tende a replicar um objeto inteiro, incluindo a sua assinatura. Por que eu sempre obter o meu nome da classe, nome do campo ... serializado, embora eu sei que dentro para fora no receptor?
  • Pense em todo o desenvolvimento da linguagem. Está ficando difícil se um dos lados usa Java, um dos lados usa C ++ ...

Alguns desenvolvedores sugerem Thrift, mas eu gostaria de usar o Google PB porque "Eu acredito em google" :-) .. De qualquer forma, vale a pena para um olhar: http://stuartsierra.com/2008/07/10/thrift-vs -protocol-buffers

O que você quer dizer com alta performance? Se você quiser mili-segundo serialização, eu sugiro que você use a abordagem de serialização que é mais simples. Se você quiser sub mili-segundo é provável que você precisa de um formato binário. Se você quer muito abaixo de 10 micro-segundos é provável que você precisa de um serialização personalizada.

Eu não tenho visto muitas referências para serialização / desserialização mas poucos menos apoio que 200 micro-segundos para serialização / desserialização.

Plataforma formatos independentes têm um custo (em esforço de sua parte e latência) você pode ter que decidir se você quer desempenho ou plataforma independência. No entanto, não há nenhuma razão você não pode ter tanto como uma opção de configuração que você alternar entre conforme necessário.

Aqui está o off a sugestão parede do dia :-) (você apenas beliscado alguma coisa na minha cabeça que eu agora quero tentar) ...

Se você pode ir para toda a solução de cache através deste que pode funcionar: Projeto Darkstar . Foi concebido como muito alto servidor do jogo desempenho, especificamente para que lê estão rapidamente (tão bom para um cache). Tem APIs Java e C então eu acredito que (pensamos que tem sido um longo tempo desde que eu olhei para ele, e eu não estava pensando isso, então) que você poderia salvar objetos com Java e lê-los de volta em C e vice-versa.

Se nada mais ele vai dar-lhe algo para ler sobre hoje: -)

Para a serialização amigável fios, considere usar a interface Externalizable. Usado de forma inteligente, você terá knowlege íntima para decidir como otimizar campos Marshall e específicos desempacotar. Dito isto, você vai precisar para gerenciar o controle de versão de cada objeto corretamente - fácil de un-marshall, mas re-empacotamento de um objeto V2 quando o código suporta V1 será ou quebrar, informações perder ou corromper dados piores de uma forma seus aplicativos não são capazes de processar corretamente. Se você está procurando um caminho ideal, cuidado com nenhuma biblioteca vai resolver seu problema sem alguns compromissos. Geralmente bibliotecas vai caber a maioria dos casos de uso e virá com o benefício adicional de que eles vão se adaptar e melhorar ao longo do tempo sem a sua entrada, se você optou por um projeto open source ativo. E eles podem adicionar problemas de desempenho, introduzir erros, e erros de correção, mesmo que não tenham afetado você ainda!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top