2012-01-13 17 views
10

Esta es una creencia común de que el reflejo es lento y trata de evitarlo tanto como sea posible. ¿Pero esa creencia es cierta en la situación actual? Ha habido muchos cambios en las versiones actuales de .net, como el uso de IL Weaving (es decir, IL Emit), etc., en oposición a las formas tradicionales de PropertyInfo y MethodInfo de realizar la reflexión.¿La reflexión es realmente lenta?

¿Es eso una prueba convincente de que el nuevo reflejo ya no es tan lento y puede utilizarse? ¿Hay una mejor manera de leer datos de atributos?

Gracias, Bhaskar

+6

"¿La reflexión es realmente lenta?" - ¿comparado con que? –

+0

+1, aunque no ejecutó los números usted mismo. Siempre he escuchado esto, sin embargo, [no puedo pensar dónde] (http://xkcd.com/125/). Aún así, nunca me impidió usar el reflejo, que nunca he encontrado lento. Según los rumores, es contradictorio, al menos cuando el código refleja el ensamblaje cargado (como suele ser el caso): si hay una cosa que usted sabe que está cargada en la memoria, ¡es el ensamble que ejecuta el código! Debería ser rápido como cualquier otra cosa. – harpo

+0

var x = new Ejemplo(); vs Activator.CreateInstance ("...."); – adt

Respuesta

11

Cuando lo piense bien, la reflexión es bastante impresionante en qué tan rápido es.

Se puede llamar a un delegado en caché de ConstructorInfo o MethodInfo con una velocidad comparable a la de cualquier otro delegado.

Un delegado creado a partir de ILGenerator.Emit (que, por cierto, no es nuevo, ha estado en .NET desde la versión 1) también se puede llamar igual de rápido.

Un objeto obtenido al emitir o llamar a un delegado ConstructorInfo será tan rápido como cualquier otro objeto.

Si obtiene un objeto cargando un ensamblaje dinámicamente, usando la reflexión para encontrar el método para llamar y llamarlo, e implementa una interfaz definida a través de la cual lo llama a partir de ese punto, entonces será simplemente tan rápido como se usa como otra implementación de esa interfaz.

En total, la reflexión nos da formas de hacer las cosas que sin ella, si pudiéramos hacerlas, tendremos que usar técnicas que son más lentas tanto para codificar como para ejecutar.

También nos ofrece medios para hacer cosas que son más complicadas, más quebradizas, menos seguras y menos efectivas que otros medios también. Casi todas las líneas del código C# pueden ser reemplazadas por una gran porción de código que utiliza la reflexión. Es casi seguro que este código será peor que la línea original en muchos aspectos, y el rendimiento es el menor de ellos.

Posiblemente el consejo de "evitar la reflexión porque es lento" parte de la creencia de que el tipo de desarrollador que se volvería loco por cualquier técnica nueva simplemente porque parecía genial sería del tipo que probablemente sería advertido por " será más lento "que por" será menos idiomático, más propenso a errores y más difícil de mantener ". Muy posiblemente esta creencia es completamente correcta.

En su mayor parte, cuando el enfoque más natural y obvio es utilizar la reflexión, entonces tampoco será menos eficaz que un intento realmente complicado para evitarlo.

Si los problemas de rendimiento se aplican a cualquier cosa en la reflexión, es realmente a los usos que se ocultan:

Usando dynamic puede parecer razonable en un caso en el que sólo un poco de trabajo podría evitarlo. Aquí vale la pena considerar la diferencia de rendimiento.

En ASP.NET, usar <%#DataBinder.Eval(Container.DataItem, "SomeProperty")%> es más fácil pero generalmente menos eficiente que <#((SomeType)Container.DataItem).SomeProperty%> o <%#SomeCodeBehindProvidedCallWithTheSameResult%>. Seguiré usando el anterior 90% del tiempo, y el último solo si realmente me importa el rendimiento de una página dada o más probablemente porque hacer muchas operaciones en el mismo objeto hace que este último sea más natural.

De modo que, en general, todo permanece "lento" en las computadoras mientras que están limitadas por el requisito de trabajar en un solo universo de una manera que consume energía y toma tiempo, por algún valor de "lento". Las diferentes técnicas de reflexión tienen costos diferentes, pero también lo hacen las alternativas. Tenga cuidado no tanto de la reflexión en los casos en que es el enfoque obvio como la reflexión oculta donde otro enfoque un poco menos obvio puede servir bien.

Y por supuesto, codifique sabiamente con cualquier técnica que use. Si va a llamar al mismo delegado cien veces seguidas, debe almacenarlo en lugar de obtenerlo en cada llamada, y eso sería si la forma de obtenerlo era a través de la reflexión o no.

0

sí la reflexión es lento cuando tratamos de hacer en opertations voluminosos o con un bucle. puede probar opciones dinámicas también. con la opción dinámica, se puede almacenar en caché y, finalmente, será más rápido que la reflexión.

7

Todo depende.
Sí, utilizando la reflexión es sin ninguna duda más lento que no se utiliza la reflexión, pero hay que mirar el cuadro grande:

Por ejemplo, imagine que su código hace una reflexión y luego carga algunos datos de una base de datos sobre el red.
En este caso, puede descuidar por completo el costo adicional de la reflexión porque la solicitud de la base de datos a través de la red demorará mucho, mucho más.

+0

+1 y para agregar a esto: 'new T()' en genéricos en realidad se compila en 'Activator.CreateInstance ()' y también podría decirse que es "uso de la reflexión". ¿Se podría escribir un código diferente por eso? No lo creo. –

0

Si necesita ver los atributos aplicados al código fuente, entonces casi tiene que usar la reflexión.

Algunas operaciones de reflexión son rápidas, como Object.GetType(), pero algunas operaciones son relativamente lentas, como Type.FindMethod ("MyMethod").

En general, diría que si su aplicación hace uso ocasional de Reflection, no debería haber ningún problema de rendimiento. Por otro lado, si su aplicación usa Reflection extensamente, entonces puede observar cierta lentitud.

1

No me preocuparía el alto costo de rendimiento. No dice que el rendimiento no importe, pero en muchos casos, un milisegundo o dos no se nota o vale la pena elegir una alternativa de codificación más complicada. Eche un vistazo here.

por lo general prefieren este enfoque:

  1. escribir código simple
  2. medir el rendimiento
  3. Optimizar el más grande bateador, si es necesario
1

Whad entiende usted por mencionar una creencia común? La reflexión no es un bloque sólido. Debes considerar cada método aparte. Por ejemplo, crear un objeto a través de un constructor predeterminado es unas pocas veces más lento que una simple llamada, mientras que la creación de un constructor con parámetros es diez veces más lenta. Entonces, si desea estudiar la velocidad, haga un punto de referencia y compare las funciones concretas que necesita.

PS. Usando C#, siempre puedes crear y compile expressions sobre la marcha, que si logras hacerlo sería mucho más rápido que la reflexión.

0

La introspección es un trabajo pesado. Decir lento es relativo a muchas cosas.La invocación del método/constructor a través de la reflexión es lenta, pero el uso de la reflexión solo para recuperar metadatas no lo es.

Tenga en cuenta que la reflexión debe usarse solo para recuperar metadatos. Si necesita invocar el método, ejecutar algo, simplemente emita tipos/métodos dinámicos en el momento de la inicialización e invocarlos a través de interfaces/delegados.