Tiago Tartari

Conteúdo

Os Riscos do AutoMapper no .NET: O que você deve Priorizar? Facilidade ou Performance?

Ao utilizar AutoMapper como um mapeador automático de objetos no .NET, algo que você deve levar em conta, é se performance extrema de fato é um atributo de qualidade que você deve alcançar no seu software. A discussão entre priorizar facilidade em detrimento à performance é uma constante no universo do desenvolvimento de software. Um exemplo clássico dessa discussão se dá na escolha entre o uso do AutoMapper, que facilita o mapeamento de objetos e reduz a quantidade de código escrito, e o mapeamento manual, que tende a ter uma performance superior. Entretanto, com a possibilidade da utilização da compilação Ahead-of-Time, a tão facilidade pode se tornar uma ação de manutenção enorme.

Utilizar AutoMapper ou o Mapeamento Manual?

O AutoMapper pode ter um desempenho insatisfatório em certos cenários de alta demanda, como por exemplo, em um e-commerce com alto volume de acessos. A utilização do AutoMapper para o mapeamento automático de qualquer objeto pode ser prejudicial, pois a alta demanda de acessos em hot path, o excesso de compilações e o tempo para que a compilação feitas pelo Just in Time (JIT) podem aumentar o tempo de resposta das requisições.

Comparando AutoMapper e Mapeamento Manual em um contexto de Compilação Ahead-of-Time (AOT)

O AutoMapper é uma biblioteca amplamente utilizada que diminui a quantidade de código necessário para realizar o mapeamento entre objetos. No entanto, essa conveniência vem ao custo de um possível impacto no desempenho. Esse impacto ocorre devido à maneira como o AutoMapper opera, usando reflection para identificar como os objetos devem ser mapeados. Esse comportamento pode criar problemas ao se optar pela compilação AOT, que realiza uma compilação estática, incompatível com as necessidades do AutoMapper.

Por outro lado, em termos de performance, o mapeamento manual tende a ser mais eficiente. No entanto, a maior eficiência do mapeamento manual pode ter um custo em termos de tempo de desenvolvimento e propensão a erros, como o esquecimento de mapear um campo.

Por isso, a decisão de usar o AutoMapper ou o mapeamento manual deve depender de uma análise ponderada das necessidades e dos objetivos do projeto. Em situações onde o tempo de resposta e a performance são críticos, pode ser mais adequado optar pelo mapeamento manual. Em outros casos, a facilidade de uso e a redução do tempo de desenvolvimento oferecidos pelo AutoMapper podem ser mais valiosos.

Em um benchmark que comparamos o AutoMapper e o mapeamento manual, vemos que o mapeamento manual é mais rápido, com um tempo médio de 28.13 ns, em comparação com 134.39 ns para o AutoMapper. Contudo, é importante considerar que essa diferença, pode não ter um impacto perceptível no desempenho de muitos aplicativos.

Comparativo de Performance entre o mapeamento manual e com o AutoMapper

A seguir estão os resultados de uma benchmark utilizando o AutoMapper e o mapeamento manual. A BenchmarkDotNet, uma biblioteca de benchmarking de alto nível para .NET, foi utilizada para realizar os testes.

MétodoMédiaErroDesvio PadrãoRazãoRazãoSDGen0AlocadoRazão de Aloc
MapeamentoManual28.13 ns0.623 ns1.140 ns1.000.000.019180 B1.00
MapeamentoAutoMapper134.39 ns2.667 ns2.739 ns4.830.250.019180 B1.0

O tempo médio de execução para o mapeamento manual é de 28.13 nanossegundos, enquanto para o AutoMapper é de 134.39 nanossegundos. Isso significa que o mapeamento manual é cerca de 5 vezes mais rápido que o AutoMapper, em média.

As colunas Error e StdDev mostram a variabilidade na execução do código. Valores mais baixos indicam resultados mais consistentes. O mapeamento manual tem um desvio padrão menor, o que sugere uma consistência mais alta em seu tempo de execução.

Os valores de Ratio e RatioSD representam a razão de tempo médio entre o mapeamento manual e o AutoMapper. Um valor de 1 para o mapeamento manual significa que ele é usado como referência. O valor 4.83 para o AutoMapper significa que ele demora aproximadamente 4.83 vezes mais tempo para executar em comparação com o mapeamento manual.

Ao falarmos de memória a Gen0 refere-se à geração 0 do coletor de lixo do .NET, que é a primeira linha de coleta de objetos descartados. Aqui, ambos os métodos estão produzindo a mesma quantidade de lixo, portanto, não há diferença significativa em termos de alocação de memória ou pressão no coletor de lixo. Enquanto isso, Allocated refere-se a quantidade de memória alocada para cada método é de 80 Bytes, o que é insignificante e, novamente, não mostra diferenças significativas entre as duas abordagens. Por fim, o Alloc Ratio representa a razão da quantidade de memória alocada entre os dois métodos. Como ambos estão alocando a mesma quantidade de memória, a razão é 1.

A partir destes dados, podemos concluir que, enquanto o AutoMapper é significativamente mais lento do que o mapeamento manual, a diferença em termos de alocação de memória e pressão sobre o coletor de lixo é mínima. Portanto, a decisão entre usar um ou outro pode depender mais dos requisitos específicos do projeto e da necessidade de otimização de desempenho.

As diferenças na Intermediate Language entre o mapeamento manual e o AutoMapper

Depois de justificar que o mapeamento manual é consideravelmente mais rápido que o AutoMapper, precisamos justificar o que aconteceu para essa performance ser superior dado o Intermediate Language.

A análise do código IL nos revela algumas diferenças importantes entre as abordagens:

Abordagem de Mapeamento

  • O mapeamento manual realiza a cópia individual de cada atributo entre objetos.
  • O AutoMapper realiza o mapeamento de forma automática e declarativa, seguindo regras predefinidas.

Quantidade de Instruções

  • A abordagem manual envolve uma sequência repetitiva de instruções para cada atributo, aumentando a quantidade de código.
  • O mapeamento com o AutoMapper utiliza menos instruções, tornando o código mais conciso e fácil de manter.

Stack Size

  • A abordagem manual requer menos espaço na pilha de avaliação (maxstack definido como 3).
  • O mapeamento com o AutoMapper requer mais espaço na pilha de avaliação (maxstack definido como 8), devido a chamadas mais complexas ao AutoMapper.

Justificativas para adotar ou não o AutoMapper

A tabela de comparação revela uma distinção marcante entre as abordagens de mapeamento manual e AutoMapper em termos de performance, simplicidade e flexibilidade.

MétricaMapeamento ManualAutoMapper
DesempenhoMuito altoMenor
FlexibilidadeBaixaAlta
Facilidade de usoMenorMaior
ManutençãoAltaBaixa

Desempenho: O mapeamento manual ganha na performance, sendo mais eficiente e rápido. Isso se deve ao fato de que ele realiza uma série direta de operações de carga e armazenamento, enquanto o AutoMapper requer chamadas de métodos e operações internas adicionais, que podem atrasar o processo.

Flexibilidade: O AutoMapper tem uma vantagem em termos de flexibilidade. Ele permite um mapeamento de objetos complexos e personalizados com menos código e esforço, adaptando-se facilmente a novos requisitos e alterações. O mapeamento manual, embora eficiente, é menos flexível pois requer a escrita de código específico para cada mapeamento.

Facilidade de Uso: O AutoMapper brilha em termos de facilidade de uso. Ele abstrai a complexidade do mapeamento de objeto para objeto, tornando o código mais fácil de ler e de escrever. No mapeamento manual, cada mapeamento deve ser escrito explicitamente, o que pode ser mais trabalhoso e propenso a erros.

Manutenção: Em termos de manutenção, o mapeamento manual pode ser mais exigente. Qualquer alteração no modelo de dados requer a atualização do código de mapeamento correspondente. Por outro lado, o AutoMapper, devido à sua flexibilidade e capacidade de gerar mapeamentos dinamicamente, geralmente requer menos manutenção.

Enfim, essa análise demonstra que a escolha entre mapeamento manual e AutoMapper depende fortemente dos requisitos específicos do projeto e das prioridades do negócio. Se a performance for o principal fator, o mapeamento manual pode ser a melhor escolha. No entanto, se a flexibilidade, facilidade de uso e manutenibilidade forem mais importantes, o AutoMapper pode ser preferível.

Conclusão

Com base na análise de desempenho, do IL gerado e de todos os outros aspectos discutidos, é evidente que o AutoMapper, embora uma ferramenta extremamente útil e produtiva, pode trazer desafios quando usamos compilação Ahead-of-Time (AOT).

A diferença principal entre os métodos Manual e AutoMapper reside na forma como eles operam internamente. Enquanto o método Manual faz um mapeamento direto das propriedades, o AutoMapper usa Reflection e um cache interno para realizar o mapeamento, o que acaba demandando mais tempo.

Ao analisar o IL gerado, percebemos que o AutoMapper tem uma maior complexidade na geração do código, o que explica a diferença no tempo de execução quando comparado ao mapeamento manual. Este tempo extra pode não ser perceptível em operações menores, mas em aplicações de alta carga pode se tornar um fator a ser considerado.

Mas o ponto mais crítico reside no uso do AutoMapper com a compilação AOT. O AutoMapper depende do Just in Time (JIT) para funcionar corretamente devido à sua estrutura que usa reflection para fazer o mapeamento. AOT, por outro lado, realiza uma compilação estática e, portanto, não é compatível com o AutoMapper.

A decisão de usar ou não o AutoMapper depende do contexto do projeto. Se a aplicação não requer uma performance extremamente alta e não usa compilação AOT, o AutoMapper é uma excelente opção que oferece produtividade e evita possíveis erros humanos no mapeamento manual. No entanto, se o projeto é crítico em termos de performance ou se usa a compilação AOT, é melhor considerar outras opções ou fazer o mapeamento manual.

O mais importante é fazer uma análise adequada considerando o contexto e as necessidades específicas do seu projeto antes de decidir o caminho a seguir. Sempre lembre que as decisões técnicas devem estar alinhadas aos objetivos do negócio.

FAQ: Perguntas Frequentes

1. AutoMapper não é apropriado para todos os projetos?

Não, a aplicação do AutoMapper depende das necessidades do projeto. Em cenários onde a performance é um atributo de qualidade crucial, o mapeamento manual pode ser mais adequado.

2. AOT e AutoMapper não são compatíveis?

Correto, a natureza de reflexão e uso de cache do AutoMapper faz com que ele dependa da compilação JIT para funcionar corretamente, enquanto o AOT realiza uma compilação estática.

3. Qual abordagem tem melhor desempenho, mapeamento manual ou com AutoMapper?

O mapeamento manual geralmente tem melhor desempenho. Entretanto, a escolha entre as duas deve considerar vários fatores, incluindo a complexidade do mapeamento, a necessidade de manutenibilidade, a performance desejada, entre outros.

Compartilhe:

Tiago Tartari

Tiago Tartari

Eu ajudo e capacito pessoas e organizações a transformar problemas complexos em soluções práticas usando a tecnologia para atingir resultados extraordinários.

Qual é o desafio
que você tem hoje?