Fala galera!
Antes de começar o post, 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 no qual eu ajudei a organizar.
Neste primeiro post do ano, 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 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 deserializar 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 = $"Cliente{i}", UltimoNome = $"UltimoNome{i}", Enderecos = new List<Endereco>() { new Object.Endereco() { Bairro = $"Bairro{i}", Cidade = $"Cidade{i}", Complemento = $"Complemento{i}", Logradouro = $"Logradouro{i}", Pais = $"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 post está no meu GitHub clicando aqui
A documentação do Protobuf pode se encontrada clicando aqui
Abs e até a próxima