¿Qué tan costoso es la reflexión de .NET?

Constantemente escucho lo malo que es usar el reflection. Aunque generalmente evito la reflexión y rara vez encuentro situaciones en las que es imposible resolver mi problema sin ella, me preguntaba …

Para aquellos que han usado la reflexión en las aplicaciones, ¿han medido los éxitos de rendimiento y realmente es tan malo?

Es. Pero eso depende de lo que estás tratando de hacer.

Uso el reflection para cargar ensamblajes dinámicamente (complementos) y su “penalización” de rendimiento no es un problema, ya que la operación es algo que hago durante el inicio de la aplicación.

Sin embargo, si estás reflejando dentro de una serie de bucles nesteds con llamadas de reflexión en cada uno, diría que deberías revisar tu código 🙂

Para operaciones “un par de veces”, la reflexión es perfectamente aceptable y no notará ninguna demora o problema con ella. Es un mecanismo muy poderoso e incluso lo usa .NET, así que no veo por qué no debes intentarlo.

En su conferencia The Performance of Everyday Things , Jeff Richter muestra que llamar a un método por reflexión es aproximadamente 1000 veces más lento que llamarlo normalmente.

Consejo de Jeff: si necesita llamar al método varias veces, use el reflection una vez para encontrarlo, luego asígnelo a un delegado y luego llame al delegado.

El rendimiento de la reflexión dependerá de la implementación (las llamadas repetitivas se deben almacenar en caché, p. Ej .: entity.GetType().GetProperty("PropName") ). Dado que la mayor parte de la reflexión que veo en el día a día se usa para poblar entidades de lectores de datos u otras estructuras de tipo repository, decidí comparar el rendimiento específicamente en la reflexión cuando se usa para obtener o establecer las propiedades de un objeto.

Ideé una prueba que creo que es justa, ya que guarda en caché todas las llamadas repetitivas y solo las llamadas reales SetValue o GetValue. Todo el código fuente para la prueba de rendimiento está en bitbucket en: https://bitbucket.org/grenade/accessortest . El escrutinio es bienvenido y alentado.

La conclusión a la que he llegado es que no es práctica y no proporciona mejoras de rendimiento notables para eliminar la reflexión en una capa de acceso a datos que devuelve menos de 100.000 filas a la vez cuando la implementación de la reflexión se realiza bien.

Gráfico de tiempo (y) contra el número de entidades pobladas (x)

El gráfico anterior muestra el resultado de mi pequeño punto de referencia y muestra que los mecanismos que superan al reflection, solo lo hacen notablemente después de la marca de los 100.000 ciclos. La mayoría de los DAL solo devuelven varios cientos o quizás miles de filas a la vez y en estos niveles la reflexión funciona perfectamente.

Mi experiencia más pertinente fue escribir código para comparar dos entidades de datos del mismo tipo en un modelo de objeto grande en cuanto a propiedad. Lo tengo trabajando, lo intenté, corrí como un perro, obviamente.

Estaba abatido, y de la noche a la mañana me di cuenta de que, sin cambiar la lógica, podría usar el mismo algoritmo para autogenerar métodos para hacer la comparación, pero accediendo estáticamente a las propiedades. No tardé en adaptar el código para este propósito y tuve la capacidad de hacer una comparación profunda de las entidades con el código estático que podía actualizarse con el clic de un botón cada vez que cambiaba el modelo del objeto.

Mi punto es: en conversaciones con colegas, ya que varias veces he señalado que su uso de la reflexión podría ser la autogeneración del código para comstackr en lugar de realizar operaciones en tiempo de ejecución, y esto a menudo vale la pena considerar.

Si no estás en un bucle, no te preocupes por eso.

No masivamente. Nunca he tenido problemas en el desarrollo de computadoras de escritorio, a menos que, como dice Martin, lo estés utilizando en una ubicación estúpida. He oído que muchas personas tienen temores totalmente irracionales sobre su desempeño en el desarrollo de escritorio.

Sin embargo, en el Marco Compacto (en el que normalmente estoy) es casi un anatema y debe evitarse como la peste en la mayoría de los casos. Todavía puedo salí con la costumbre de usarlo con poca frecuencia, pero tengo que ser muy cuidadoso con su aplicación, que es mucho menos divertida. 🙁

Ya es suficientemente malo que tenga que preocuparse incluso por la reflexión realizada internamente por las bibliotecas .NET para el código de rendimiento crítico.

El siguiente ejemplo es obsoleto: verdadero en el momento (2008), pero hace mucho tiempo corregido en versiones más recientes de CLR. Sin embargo, ¡la reflexión en general sigue siendo algo costosa!

Ejemplo: nunca debe usar un miembro declarado como “Objeto” en una instrucción de locking (C #) / SyncLock (VB.NET) en código de alto rendimiento. ¿Por qué? Debido a que CLR no puede bloquear en un tipo de valor, lo que significa que tiene que hacer una comprobación de tipo de reflexión en tiempo de ejecución para ver si su objeto es realmente un tipo de valor en lugar de un tipo de referencia.

Como con todas las cosas en la progtwigción, tiene que equilibrar el costo de rendimiento con cualquier beneficio obtenido. La reflexión es una herramienta invaluable cuando se usa con cuidado. Creé una biblioteca de mapeo O / R en C # que usó la reflexión para hacer los enlaces. Esto funcionó fantásticamente bien. La mayor parte del código de reflexión solo se ejecutó una vez, por lo que cualquier impacto en el rendimiento fue bastante pequeño, pero los beneficios fueron excelentes. Si estuviera escribiendo un nuevo algoritmo de clasificación fandangled, probablemente no usaría el reflection, ya que probablemente escalaría pobremente.

Aprecio que no haya respondido exactamente su pregunta aquí. Mi punto es que en realidad no importa. Use la reflexión cuando sea apropiado. Es solo otra característica del idioma que necesita para aprender cómo y cuándo usarla.

La reflexión puede tener un impacto notable en el rendimiento si la usa para la creación frecuente de objetos. Desarrollé una aplicación basada en el bloque de aplicaciones de interfaz de usuario compuesta, que depende mucho de la reflexión. Hubo una degradación notable del rendimiento relacionada con la creación de objetos a través de la reflexión.

Sin embargo, en la mayoría de los casos no hay problemas con el uso de la reflexión. Si su única necesidad es inspeccionar algún conjunto, recomendaría Mono.Cecil que es muy liviano y rápido

La reflexión es costosa debido a las numerosas comprobaciones que debe realizar el tiempo de ejecución siempre que solicite un método que coincida con una lista de parámetros. En algún lugar, en el fondo, existe un código que recorre todos los métodos para un tipo, verifica su visibilidad, comprueba el tipo de devolución y también comprueba el tipo de cada parámetro. Todo esto cuesta tiempo.

Cuando ejecuta ese método internamente, hay algún código que hace cosas como verificar que pasó una lista de parámetros compatible antes de ejecutar el método de destino real.

Si es posible, siempre se recomienda que uno almacene en caché el control del método si se va a reutilizar continuamente en el futuro. Como todos los buenos consejos de progtwigción, a menudo tiene sentido evitar repetirse. En este caso, sería un desperdicio buscar continuamente el método con ciertos parámetros y luego ejecutarlo cada vez.

Examine la fuente y observe lo que se está haciendo.

Como con todo, se trata de evaluar la situación. En DotNetNuke hay un componente bastante central llamado FillObject que utiliza la reflexión para rellenar objetos de datarows.

Este es un escenario bastante común y hay un artículo en MSDN, Uso de Reflection to Bind Business Objects a ASP.NET Form Controls que cubre los problemas de rendimiento.

Dejando a un lado el rendimiento, una cosa que no me gusta de la reflexión en ese escenario en particular es que tiende a reducir la capacidad de comprender el código de un vistazo rápido que para mí no parece valer la pena cuando consideras que también pierdes recostackción seguridad de tiempo en lugar de conjuntos de datos fuertemente tipados o algo así como LINQ to SQL .

La reflexión no reduce drásticamente el rendimiento de su aplicación. Es posible que pueda hacer ciertas cosas más rápido al no usar la reflexión, pero si la Reflexión es la manera más fácil de lograr alguna funcionalidad, entonces úsela. Siempre puede refactorizar su código lejos de Reflection si se convierte en un problema de perf.

Creo que encontrarás que la respuesta es, depende. No es un gran problema si desea ponerlo en su aplicación de lista de tareas. Es un gran problema si quieres ponerlo en la biblioteca de persistencia de Facebook.