with example convert .net reflection reflection.emit propertyinfo

.net - example - ¿Por qué PropertyInfo SetValue y GetValue son tan lentos?



convert string to propertyinfo c# (2)

¿Por qué los métodos PropertyInfo para obtener y configurar una propiedad son tan lentos? Si construyo un delegado usando Reflection.Emit , es mucho más rápido.

¿Están haciendo algo importante, para que el tiempo que toman pueda ser justificado? Eso es ... ¿me estoy perdiendo algo al usar Reflection.Emit compilar delegados en lugar de usar el valor de GetValue y SetValue de PropertyInfo (aparte de la velocidad de desarrollo)?

PD: ¡Por favor, evidencia, no solo adivinando!


La implementación de RuntimePropertyInfo (que es la subclase concreta de PropertyInfo para los tipos de tiempo de ejecución) implementa GetValue y SetValue invocando los métodos de SetValue y SetValue través de la reflexión ( MethodInfo.Invoke ), mientras que su delegado generado probablemente llame directamente a los métodos. Por lo tanto, la pregunta se reduce a: ¿por qué RuntimeMethodInfo.Invoke es tan lento en comparación con una invocación compilada?

Cuando descompilas (o miras las fuentes de referencia para) RuntimeMethodInfo.Invoke , puedes ver que esto es probablemente porque Invoke realiza muchas tareas:

  • realiza comprobaciones de coherencia (¿el número y los tipos de parámetros pasados ​​coinciden con la firma? ¿coincide la instancia pasada con el tipo de declaración? ¿se pasó una instancia aunque el método es estático?),
  • realiza visibilidad y (si se evitan los controles de visibilidad) controles de seguridad,
  • desenvuelve la matriz de parámetros, tratando los parámetros de ref de una manera especial para que puedan escribirse más adelante,
  • Unboxes parámetros si es necesario,
  • debe encontrar el puntero del método en función del identificador de tipo de tiempo de ejecución y del identificador de método asociado con RuntimeMethodHandle y luego invocar el método,
  • encierra el valor de retorno si es necesario, y
  • encaja y coloca en la matriz de parámetros cualquier parámetro de ref / out.

El tiempo de ejecución realizará verificaciones similares de consistencia, seguridad y visibilidad cuando compile a su delegado en un código nativo ejecutable. También emite código para boxeo / desempaquetado, etc. Sin embargo, solo necesita hacer estas cosas una vez, y luego puede garantizar que el código es seguro de ejecutar. Esto hace que el método real sea una operación muy barata (cargar los parámetros y saltar a la dirección del método).

En contraste, cada llamada a RuntimeMethodInfo.Invoke (y por lo tanto a GetValue / SetValue ) necesita repetir todo el trabajo, ya que el contexto (parámetros, instancia y uso del tipo de retorno) no se conoce. Y esta es probablemente la razón por la que es tan lento.

Acerca de lo que podría faltar: si emite sus propios delegados de invocación de propiedad, por supuesto, deberá lidiar con el boxeo / desempaquetado, los parámetros de ref / out, etc.


No hay necesidad de usar Emit. Es mucho más fácil de usar Expression. Puede acelerar el acceso como se describe en SO . La clase auxiliar crea un "puntero de método" (Acción / Función) para el getter o setter. Si reutiliza Action / Func podrá realizar tan rápido como un configurador normal.

// creating setter (once) var propertyInfo = typeof(T).GetProperty(field); var setter = FastInvoke.BuildUntypedSetter<T>(propertyInfo)); // usage somehow later in a loop of data foreach(var myobject in MySource) { setter(myobject, myValue) }