Este é um post escrito em 2019, o original foi escrito no Medium e passei para cá
Protocol Buffers ou protobuf para os íntimos é um método de serialização de dados estruturados, criado pela Google para comunicação entre serviços internos, com ele você cria um arquivo de configuração, arquivo .proto, com sua estrutura de dados e importa na sua linguagem favorita e gerar suas classes de Dados.
Nele definimos o tipo dos dados, as estruturas, obrigatoriedade, valores default, etc. Existe uma documentação completa mas um ponto que devemos prestar atenção é que existe um numero único para cada campo, ele deve ser único dentro da sua estrutura e serve para identificação do campo dentro da formatação binária.
Então ele é igual Json e XML?
Sim e não, ele é sim um tipo de serialização mas ele é mais completo, mais simples e mais leve.
Podemos importar o arquivo .Proto com um utilitário, feito com .NET para gerar nossa classe de Data.
dotnet tool install --global protobuf-net.Protogen --version 2.3.17
Após instalado podemos executar o comando abaixo para gerar nosso código com qualquer arquivo .proto.
protogen <File> --csharp\_out=<Output>
Ele irá gerar o código abaixo
Dica: Existe um site que faz exatamente esse processo, caso não queira instalar a global tool
Pra quem já utilizou web services SOAP, isso se parece muito com o arquivo que é gerado com WSDL, mas calma não morra do coração, não é isso, ele é só um arquivo de modelo, com isto você não consegue efetuar chamadas diretamente para o webservice, e quando você olha com mais atenção vê que não tão feio quanto o gerado pelo WSDL.
Com isso podemos utilizar o pacote Google.Protobuf e serializar de forma simples:
Protobuf-net
O protobuf-net é uma library criada para facilitar a utilização de protobuf em Dot Net, ele suporta tanto classes com Data Annotations, bem parecido com o antigo JsonProperty, quanto o arquivo .proto, eu gosto mais dele pois as classes ficam mais legíveis do que com o pacote do google, para o exemplo irei usar Data Annotation pra facilitar a minha vida ¯\_(ツ)_/¯.
Vou iniciar criando meus modelos, resolvi criar 2 tipos de modelos, um com somente uma propriedade do tipo Int, e outro com alguns campos a mais e o model mais simples, adiciono a Data Annotation [ProtoContract] nas classes e os [ProtoMember()] nas propriedades.
Como dar pra perceber, diferente de Json ou XML, não existe um nome para os campos, como por exemplo [JsonProperty(“MyString”)], ao invés disso cada campo tem um inteiro como identificador, que não pode se repetir na sua classe, sem esse Annotation o campo não será serializado.
Dica: ele não aceita números negativos e números menores ocupam menos espaço, não comece em 100000000 XD.
Tá, é só isso?
Não, mas vamos fazer o código de serialização em protobuf junto com um código de serialização em Json para vermos se realmente tem alguma diferença no desempenho, vou usar o Benchmark Dot Net pra me auxiliar e o Bogus para criar alguns dados fake.
Montei 4 tipos de testes, um para cada tipo de serialização, totalizando 8 sendo eles:
- Serializar SimpleClass;
- Serializar ComplexClass;
- Serializar uma lista com 10 ComplexClass;
- Serializar uma lista com 100 ComplexClass.
Bom então vamos modificar nosso método Main e iniciar o teste
Fiz o Build da aplicação em release e executei-a por linha de comando, o resultado é este:
Resultado do Benchmark efetuado
Esse é um Benchmark bem simples mas podemos perceber diminuição alocação de memoria e tempo gasto na operação ,principalmente conforme ela vai aumentando a quantidade, são bem menores com o Protobuf-net, fiz alguns outros testes e usando a biblioteca do Google você consegue ganhar mais um pouco de desempenho.
Existem alguns benchmarks mais completos na internet caso queira saber mais, por exemplo este e este dentre outros
Então vou usar protobuf pra tudo?
Calma jovem padawan, não é para tudo que devemos usar, Json ainda é muito bom para os seguinte casos na minha opnião:
- Você precisa que seus dados sejam legíveis para humanos;
- Você vai integra com algum cliente (afinal seu cliente pode não fazer ideia do que é protobuf);
- Seus dados são dinâmicos (não existe um schema);
- Sua aplicação que irá consumir os dados é em Javascript ou um Browser.
Mas para comunicação interna entre seus serviços, cache, filas e etc você pode usar protobuf sem problemas :D