Fala, galera!
Antes de começar o artigo, gostaria de compartilhar com vocês que tive a grande honra de me tornar MVP (Microsoft Most Valuable Professional). Com isso, poderei ajudar ainda mais a comunidade com meus artigos, eventos e etc. Deixo o meu muito obrigado a todos que ajudaram de alguma forma, lendo meus artigos, comentando ou indo a eventos nos quais eu ajudei a organizar.
Neste artigo irei falar de uma biblioteca chamada Protobuf.
Essa biblioteca é de extrema valia quando precisamos serializar uma grande quantidade de dados e com uma performance excepcional. Muitas das vezes fazer parse de JSON ou XML não é ideal quando estamos falando de objetos grandes com alguns megas de dados. Neste tipo de cenário uma serialização em formato binário é muito mais eficiente.
A biblioteca Protobuf tem algumas particularidades, como:
- [ProtoContract]: indica que a classe será serializada usando o Protobuf
- [ProtoMember]: indica que a propriedade/field deverá ser serializada usando o Protobuf
- [ProtoIgnore]: indica que a propriedade/field será ignorada quando uma serialização ocorrer
Outras características do Protobuf:
- A serialização do Protobuf ignora a interface ISerializable
- Não é possível customizar a serialização do Protobuf usando a interface ISerializable
Show me the code!
Para usar o Protobuf, basta instalar usando o Package Manager Console através do comando abaixo:
Install-Package protobuf-net
Para esse exemplo criei uma classe chamada Cliente e Endereço e anotei com os atributos do Protobuf, conforme no exemplo abaixo:
[ProtoContract()]
public class Cliente
{
[ProtoMember(1)]
public string PrimeroNome { get; set; }
[ProtoMember(2)]
public string UltimoNome { get; set; }
[ProtoMember(3)]
public DateTime DataNascimento { get; set; }
[ProtoMember(4)]
public List<Endereco> Enderecos { get; set; }
}
[ProtoContract()]
public class Endereco
{
[ProtoMember(1)]
public string Logradouro { get; set; }
[ProtoMember(2)]
public string Complemento { get; set; }
[ProtoMember(3)]
public string Bairro { get; set; }
[ProtoMember(4)]
public string Cidade { get; set; }
[ProtoMember(5)]
public string Pais { get; set; }
}
Feito isso, criei uma classe estática que servirá para serializar e desserializar os objetos.
public static class ProtoSerialize
{
public static byte[] Serialize<T>(T obj) where T : class
{
if (obj == null)
return new byte[] { };
using(var stream = new MemoryStream())
{
ProtoBuf.Serializer.Serialize<T>(stream, obj);
return stream.ToArray();
}
}
public static T Deserialize<T>(byte[] data) where T : class
{
if (data == null)
return default(T);
using (var stream = new MemoryStream(data))
{
return ProtoBuf.Serializer.Deserialize<T>(stream);
}
}
}
Para rodar nosso projeto eu criei um Console Application. Nele temos um teste de desempenho usando a biblioteca Newtonsoft.json, umas das mais famosas bibliotecas para se converter objetos C# em JSON.
static void Main(string[] args)
{
var stopWatch = Stopwatch.StartNew();
for (int i = 0; i < 5000000; i++)
{
var obj = CreateCliente(i);
Newtonsoft.Json.JsonConvert.SerializeObject(obj);
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
Console.WriteLine("RunTime Json " + elapsedTime);
var stopProto = Stopwatch.StartNew();
for (int i = 0; i < 5000000; i++)
{
var obj = CreateCliente(i);
Protobuf.Serializer.ProtoSerialize.Serialize<Cliente>(obj);
}
stopProto.Stop();
TimeSpan tsProto = stopProto.Elapsed;
string elapsedTimeProto = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", tsProto.Hours, tsProto.Minutes, tsProto.Seconds, tsProto.Milliseconds / 10);
Console.WriteLine("RunTime Proto " + elapsedTimeProto);
Console.Read();
}
private static Cliente CreateCliente(int i)
{
return new Object.Cliente()
{
DataNascimento = DateTime.Now,
PrimeroNome = quot;Cliente{i}",
UltimoNome = quot;UltimoNome{i}",
Enderecos = new List<Endereco>()
{
new Object.Endereco()
{
Bairro = quot;Bairro{i}",
Cidade = quot;Cidade{i}",
Complemento = quot;Complemento{i}",
Logradouro = quot;Logradouro{i}",
Pais = quot;Pais{i}"
}
}
};
}
A velocidade de serialização dos objetos usando o Protobuf chega a ser 17s mais rápido em relação ao Newtonsoft.json.

Abaixo uma gráfico de comparação de performance em relação a outras bibliotecas.

O código deste artigo está no meu GitHub; você pode acessá-lo clicando aqui.
A documentação do Protobuf pode se encontrada neste link.
Abraços e até a próxima!




