Reflexão: O uso da reflexão ainda é "ruim" ou "lento"? O que mudou com a reflexão desde 2002?

21

Notei que, ao lidar com expressões ou árvores de expressão, estou usando muito a reflexão para definir e obter valores nas propriedades e no que você tem. Ocorreu-me que o uso da reflexão parece estar se tornando cada vez mais comum. Coisas como DataAnotations para validação, ORMs pesados ​​de atributos, etc. Pergunte-me: O que mudou desde os dias anos e anos atrás, quando eu era instruído a evitar a reflexão, se possível?

E daí, se alguma coisa mudou? É apenas a velocidade das máquinas? Houve mudanças na estrutura para acelerar a reflexão?

Ou nada mudou realmente? Ainda é "ruim" ou "lento" usar a reflexão?

blesh
fonte
2
O reflexo sempre será mais lento que as chamadas diretas, porque você precisa executar várias etapas para encontrar e verificar se o que você está chamando existe.
Michael K
Sempre foi ruim ... É claro que às vezes você não tem escolha, cabe ao programador saber quando esses tempos são e evitá-lo de outra forma.
Ramhound
Executar um Reflection com gettype para puxar um item em uma enumeração ainda é 30 vezes mais rápido do que lançar uma exceção com Enum.Parse (). Então a reflexão ganha às vezes.
precisa saber é o seguinte

Respostas:

16

A reflexão não é ruim nem lenta. É simplesmente uma ferramenta. Como todas as ferramentas, é muito valioso para certos cenários, não tão valioso para outros.

Se o desempenho é realmente um problema, você sempre pode usar uma biblioteca como o FasterFlect .

Leitura adicional
Se a reflexão é ineficiente, quando é mais apropriada?

Robert Harvey
fonte
Ou dynamic- aparentemente, uma ordem de magnitude mais rápida que a reflexão.
Oded
1
O desempenho não é um problema. Lembro-me vividamente das pessoas que evitavam a reflexão em 2002 como se fosse uma praga. Eu estou querendo saber o que mudou desde então.
Blesh
3
@blesh: nada. As pessoas estão mais familiarizadas com isso agora e com menos medo.
22412 Robert
5
Eu poderia ser tudo "saia do meu gramado" aqui e dizer que Lisp tinha isso muito antes OOP existia ...
Michael K
Justo. Eu só estava pensando se foi o aumento de velocidade nas máquinas nos últimos dez anos que fez a diferença ou se realmente houve alterações no System.Reflection que aumentaram o desempenho.
Blesh
17

A razão pela qual as pessoas têm receio de usar a reflexão desnecessariamente não é o desempenho: sim, há alguma sobrecarga no uso da reflexão, mas, muitas vezes, resolver o problema sem ele requer uma abordagem diferente com complexidade comparável e, mesmo que não, a sobrecarga é raramente significativo (especialmente para o desenvolvimento no nível do aplicativo).

Usando a reflexão, algumas suposições importantes que normalmente se pode fazer sobre o código-fonte são desfeitas e ferramentas como "Localizar todas as referências" deixam de funcionar de maneira confiável. O Reflection também basicamente remove a maior parte da segurança de tipo que o compilador aplica, digamos, C #, e a maioria dos erros de programação que um sistema de tipo normalmente captura e traduz em erros do compilador, agora se tornam erros de tempo de execução na melhor das hipóteses ou, na pior das hipóteses, erros muito obscuros.

Então, por que as pessoas usam a reflexão então? Simplificando, porque apesar dos problemas descritos acima, é uma ferramenta muito valiosa. Pensando bem, alguns dos benefícios da programação dinâmica podem ser obtidos em uma linguagem estática e estritamente tipada como C #, e as linguagens de programação dinâmica demonstraram seus méritos recentemente, especialmente no campo da programação na Web - PHP, Javascript e Python com bastante destaque. , todos usam digitação dinâmica e provaram ser bons ajustes para programação na Web. Mas como o idioma ainda é C #, você pode optar por manter a maior parte do seu aplicativo em um idioma OOP estritamente digitado e escrever a pequena parte em que o comportamento dinâmico realmente faz diferença com a reflexão.

Um exemplo típico é quando você precisa expor métodos como chamadas de serviço da Web (usando um protocolo ainda não incorporado no .NET). A abordagem OOP estritamente tipificada funciona, mas é excessivamente restritiva e desajeitada. Mas se você usar a reflexão para mapear chamadas para métodos e pares de chave / valor para argumentos, poderá escrever o encanamento para um serviço da Web uma vez e usá-lo em qualquer classe que desejar.

tdammers
fonte
13

A reflexão ainda é significativamente mais lenta que as chamadas diretas. Duas coisas mudaram:

  • Os tempos de execução otimizam os mecanismos de reflexão para que a diferença se torne menor
  • As CPUs ficaram mais rápidas, de modo que pequenas ineficiências são mais fáceis de tolerar

Juntos, esses dois fatores reduziram o custo da reflexão até o ponto em que você pode usá-lo rotineiramente (quando apropriado a partir de um POV de manutenção) e aguardar que o criador de perfil informe se é realmente um gargalo (e tenha certeza de que a maioria dos o tempo não será).

Michael Borgwardt
fonte
4
infelizmente, as CPUs tornaram-se mais lentas - normalmente em dispositivos móveis e no servidor em que as pessoas estão tentando extrair o máximo de eficiência possível de seus servidores devido aos custos de operá-las.
Gbjbaanb
@gbjbaanb: Eu darei a você dispositivos móveis, mas no servidor, comprar mais hardware em vez de otimizar o código é a escolha aceita e racional na grande maioria dos casos, porque os custos de compra e execução de servidores são muito mais baixos do que os custos de otimização de código.
22612 Michael Borgwardt
2
Em algumas situações, os custos do servidor superam drasticamente os custos de desenvolvimento. Em estilo de grande escala. Embora os servidores sejam buff, o desempenho pode ser ainda mais crítico do que em uma máquina cliente. É um cenário caso a caso.
Lord Tydus 7/12/12
1
@ Lord Tydus: claro, mas o caso que você descreve é ​​a rara exceção.
22712 Michael Borgwardt