2009-03-11 10 views
38

Estaba hurgando en XNA y vi que la clase Vector3 estaba usando campos públicos en lugar de propiedades. Probé un punto de referencia rápido y descubrí que, para un struct, la diferencia es bastante dramática (al agregar dos vectores juntos, 100 millones de veces tomaron 2.0 con propiedades y 1.4 con campos). Para un tipo de referencia, la diferencia no parece ser tan grande, pero está allí.¿Por qué los campos públicos son más rápidos que las propiedades?

Entonces, ¿por qué es eso? Sé que una propiedad está compilada en los métodos get_X y set_X, que incurriría en una sobrecarga de llamada a un método. Sin embargo, ¿estos simples getters/setters siempre se introducen en el JIT? Sé que no se puede garantizar lo que el JIT decide hacer, pero seguramente esto es bastante alto en la lista de probabilidades. ¿Qué más hay que separa un campo público de una propiedad en el nivel de la máquina?

Y una cosa que me he estado preguntando: ¿cómo es una propiedad auto implementada (public int Foo { get; set; }) 'mejor' OO-design que un campo público? O mejor dicho: ¿cómo son esos dos diferente? Sé que convertirlo en una propiedad es más fácil con la reflexión, pero ¿algo más? Apuesto a que la respuesta a ambas preguntas es la misma.

BTW: Estoy utilizando .NET 3.5 SP1 que creo que los problemas resueltos en métodos con estructuras (o métodos de estructuras, no estoy seguro) no estaban alineados en, por lo que no lo es. Creo que lo estoy usando al menos, ciertamente está instalado, pero de nuevo, estoy usando Vista de 64 bits con SP1, que debería tener DX10.1, excepto que no tengo DX10.1 ..

También: sí, he estado corriendo una versión de lanzamiento :)

EDITAR: aprecio los chicos respuestas rápidas, pero indiqué que hago sabiendo que el acceso a la propiedad es una llamada a un método, pero que yo no' t saber por qué, presumiblemente, el método alineado es más lento que el acceso directo al campo.

EDIT 2: Así que creé otra struct que utiliza GetX explícita() métodos (o cómo no echo de menos mis días Java en absoluto) y que lleva a cabo el mismo si he deshabilitado en-guarnición en ella (a través de [MethodImplAttribute(MethodImplOptions.NoInlining)]) o no, entonces conclusión: los métodos no estáticos aparentemente nunca están en línea, ni siquiera en las estructuras.

Pensé que había excepciones, donde el JIT podría optmize la llamada de método virtual de distancia. ¿Por qué no puede suceder esto en estructuras que no conocen herencia y, por lo tanto, una llamada a un método solo puede apuntar a un posible método, ¿no? ¿O es porque puedes implementar una interfaz en él?

Esta es una especie de vergüenza, ya que realmente me hacen pensar acerca del uso de las propiedades en el rendimiento del material crítico, sin embargo, el uso de campos me hace sentir sucia y que también podría escribir lo que estoy haciendo en C

EDIT 3: Encontré this publicando sobre el mismo tema. Su conclusión final es que la llamada a la propiedad se optimizó. También podría haber jurado que he leído muchas veces que las propiedades simples getter/setter se alinearán, a pesar de ser callvirt en IL. Entonces, ¿me estoy volviendo loco?

EDITAR 4: Reed Copsey registró la respuesta en un comentario a continuación:

Re: Edit3 - ver mi comentario actualización: Creo que esto es JIT x86 vs x64 cuestiones JIT. el JIT en x64 no es tan maduro. Espero que MS mejore esto rápidamente a medida que más sistemas de 64 bits entren en línea todos los días. - Reed Copsey

Y mi respuesta a su respuesta:

Gracias, esta es la respuesta! Intenté forzar una compilación x86 y todos los métodos son igualmente rápidos y mucho más rápidos que el x64. Esto es realmente impactante para mí, no tenía idea de que vivía en la edad de piedra en mi sistema operativo de 64 bits. Incluiré su comentario en mi respuesta para que se destaque mejor. - JulianR

¡Gracias a todos!

+0

Pregunta: ¿Qué sucede si el campo es público pero también hay una propiedad. ¿Está inline entonces? – Quibblesome

+0

Parece que no, no. – JulianR

+1

Re: Edit3 - ver mi comentario actualizado: Creo que esto es x86 JIT vs x64 JIT problemas. el JIT en x64 no es tan maduro. Espero que MS mejore esto rápidamente a medida que más sistemas de 64 bits entren en línea todos los días. –

Respuesta

15

Edición 2:

tuve otro pensamiento potencial aquí:

Usted ha mencionado que se están ejecutando en x64. He probado este mismo problema en x86 y he visto el mismo rendimiento cuando uso propiedades automáticas frente a campos. Sin embargo, si observa las publicaciones de Connect y de la lista de correo/foro, hay muchas referencias en línea sobre el hecho de que el JIT de x64 CLR es una base de código diferente y tiene características de rendimiento muy diferentes al x86 JIT. Creo que este es un lugar donde x64 todavía está rezagado.

Además, FYI, la cosa struct/method/etc arreglada en .net 3.5sp1 estaba en el lado x86, y era el hecho de que las llamadas a métodos que tomaban estructuras como un parámetro nunca serían inlineadas en x86 antes de .net3 .5sp1. Eso es bastante irrelevante para esta discusión en su sistema.


Datos 3:

Otra cosa: cuanto a por qué está usando XNA campos. De hecho, estaba en el Game Fest donde anunciaron XNA. Rico Mariani dio una charla donde mencionó muchos de los mismos puntos que están en su blog. Parece que los amigos de XNA tenían ideas similares cuando desarrollaron algunos de los objetos centrales. Ver:

http://blogs.msdn.com/ricom/archive/2006/09/07/745085.aspx

Particularmente, echa un vistazo a el punto 2 #.


cuanto a por qué propiedades automáticas son mejores que los campos comunes:

Ellos le permiten cambiar la implementación en la versión 2 de la clase, y agregar la lógica en la propiedad rutinas get/set, según sea necesario, sin tener que cambiar su interfaz a sus usuarios finales. Esto puede tener un efecto profundo en su capacidad para mantener su biblioteca y código a lo largo del tiempo.

---- De post original - pero descubrió que no era el tema --------

estaba ejecutando un comunicado de construir fuera de VS? Esa puede ser una explicación de por qué las cosas no están siendo optimizadas. A menudo, si está ejecutando en VS, incluso una compilación de versión optimizada, el proceso de host VS deshabilita muchas funciones del JIT. Esto puede hacer que los puntos de referencia de rendimiento cambien.

+0

Sí, he intentado cerrar todas las instancias de VS y ejecutar el .exe en la carpeta Release, pero el mismo resultado (aunque ambas versiones son ligeramente más rápidas fuera de VS). Y sí, esa es una buena razón para usar propiedades incluso si no completa el get/set al principio :) – JulianR

+0

Los mejores casos de uso para los tipos struct son los que sirven para unir unas pocas variables junto con la cinta adhesiva (por ejemplo, las coordenadas de un punto).Si se supone que una estructura acepta cualquier par de enteros y los informa como X e Y, en realidad no hay ningún comportamiento útil que una versión futura del tipo pueda posiblemente agregar a los accesadores de propiedades X e Y sin romper cosas. Es mejor tener una estructura que diga qué es (un campo X y un campo Y), que mantenerlo "en secreto". – supercat

3
  • campos públicos son asignaciones directas
  • propiedades son métodos, a continuación, más código, insignificantes, pero más.
+0

Sí, sé lo que dije, pero cuando un método getter/setter está en línea, ¿no es ese el acceso directo al campo de respaldo de la propiedad también? – JulianR

+0

Julian - sí, debería. ¿Estabas corriendo en VS, sin embargo? Si es así, el proyecto de host de VS deshabilita muchas de las optimizaciones del JIT, incluso si se trata de una versión de lanzamiento. Ver mi comentario a continuación .. –

5

Lea este artículo de Vance. Explica en detalle por qué los métodos no siempre están incluidos en el JIT'er, incluso si parece completamente obvio que deberían serlo.

http://blogs.msdn.com/vancem/archive/2008/08/19/to-inline-or-not-to-inline-that-is-the-question.aspx

+0

Aquí hay un documento que analiza el costo de la alineación: tanto el tiempo de ejecución como el costo de cumplimiento (con un enfoque de GC): http://cs.anu.edu.au/~Steve.Blackburn/pubs/papers/writebarrier-ismm- 2002.pdf –

3

XNA tiene que dirigirse a la XBox 360, y el JIT en el .NET Compact Framework no es tan sofisticado como su contraparte de escritorio. El .NET CF JIT'er no alineará los métodos de propiedad.

3

Acceder a un campo es solo una referencia de memoria, mientras que usar una propiedad en realidad está invocando un método e incluye la sobrecarga de llamada a la función. La razón para usar propiedades en lugar de campos es aislar su código de los cambios y proporcionar una mayor granularidad sobre el acceso. Al no exponer directamente su campo, tiene un mayor control sobre cómo se realiza el acceso. El uso de campos automáticos le permite obtener el típico comportamiento getter/setter, pero desarrolla la capacidad de cambiar esto sin una necesidad posterior de que los cambios se propaguen a otras partes del código.

Por ejemplo, supongamos que desea cambiar el código para que el acceso a un campo esté controlado por la función del usuario actual. Si hubiera expuesto el campo públicamente, tendría que tocar cada parte del código que lo accedió. Exponerlo a través de una propiedad le permite modificar el código de propiedad para agregar su nuevo requisito , pero no da como resultado cambios innecesarios a ningún código que acceda a él.

Cuestiones relacionadas