E aí Galera!
Hoje começa uma série de posts sobre performance, começando com conversões, mas vamos passar por vários assuntos legais, como classes, estruturas de repetição, manipulação de exceptions, coleções e arrays.
Conversões
Se vamos falar sobre conversões, primeiramente devemos esclarecer de quais tipos de dados estamos falando, certo!? Os tipos de dados se dividem em Reference types e Value types. Todos os Value types são derivados de System.ValueType enquanto os Reference types derivam de System.Object.
As variáveis que provém de Value types contém diretamente o valor, ou seja, quando atribuímos uma variável para outra, uma cópia do valor é passada, já em tipos provenientes de Reference types, é passado apenas a referência do objeto.
Os Value types dividem-se em duas categorias: estruturas(structs) e enumerações(enum). Eles são armazenados em um local da memória chamado stack.
Já os Reference types dividem-se em: class, interface, delegate, object, string e dynamic. Que por sua vez são armazenados em um local da memória chamado heap. Os objetos que são armazenados na heap são coletados pelo Garbage Collector.
Todos os tipo supracitados herdam diretamente ou indiretamente da classe object, e por isso é possível converter qualquer tipo para o tipo object; e isso tem um nome:
- Boxing: converter Value types em object;
- Unboxing: converter object em Value types;
O Boxing e o Unboxing tem um custo enorme para a aplicação, vou exemplificar isso abaixo:
Temos um método, que preenche duas listas, uma genérica List<int>, e outra que recebe qualquer tipo(object), que é o ArrayList, a única diferença entre as duas é a conversão implícita que será feita quando preenchermos o ArrayList. Vejamos o resultado então:
E o que temos por aqui? Observem que o tempo para preencher a lista sem conversão é 20 vezes menor do que quando precisamos converter.
O Boxing pode aumentar o tempo até 20 vezes, e o Unboxing até 4 vezes; agora imagine isso em uma aplicação real, com vários usuários, executando várias vezes. A aplicação não vai ficar muito legal, não acha? Então evite usar conversão de value types para reference types.
Temos alguns tipos de conversão no C#, vou exemplificar também, e dizer quando devemos usar cada um deles:
Operador (), é a maneira mais simples para converter variáveis numéricas, veja:
Aqui demorou 00:00:00.0000019 na primeira execução.
Para converter strings para um tipo numérico, basta usar o Parse ou o TryParse, veja:
O operador Parse demorou 00:00:00.0000078 para a conversão, já o TryParse levou 00:00:00.0003678 para completar a tarefa. O método TryParse é mais eficiente quando podem ocorrer exceções durante a conversão, como exemplo tentar converter “abc” em int.
Ainda se preferir, pode utilizar os métodos ToBoolean, ToByte, ToChar, ToDateTime, ToDecimal, ToDouble, ToInt16, ToInt32, ToInt64, ToSByte, ToSingle, ToString, ToUInt16, ToUInt32, ToUInt64 da classe Convert, para efetuar conversões, que pode receber qualquer tipo para converter, como o exemplo a seguir:
Comparando esses tipos de conversão podemos perceber que:
- O operador () é o método mais rápido de converter um tipo em outro;
- Os métodos Parse e TryParse obtém melhor resultado de performance em relação aos métodos da classe Convert, que aliás, perde pra todos os outros métodos de conversão no quesito performance;
Os exemplos de código estão disponíveis no GitHub: https://github.com/vmussak/PerformanceExample
Por hoje é só isso, qualquer dúvida ou sugestão, estou à disposição! Até mais 😀
Eu obtive resultados semelhantes quando realizei os testes para o meu livro: Como Melhorar a Performance de Websites .NET
Conversões devem ser evitadas também quando usamos stored procedures.
GostarLiked by 1 person
Muito bem lembrado Alfredo, conversão nas procedures também são um ponto a ser discutido! Muitos pontos que eu levantei me espelhei no seu livro, muito bom!
GostarGostar