Si encuentras algo que no comprendes puedes comentarlo y te responderemos lo más rápido posible.
Solución:
En teoría, un static El método debería funcionar un poco mejor que un método de instancia, en igualdad de condiciones, debido al extra oculto this
parámetro.
En la práctica, esto hace tan poca diferencia que quedará oculto en el ruido de varias decisiones del compilador. (Por lo tanto, dos personas podrían “probar” una mejor que la otra con resultados en desacuerdo). No menos importante desde el this
normalmente se pasa en un registro y, para empezar, a menudo se encuentra en ese registro.
Este último punto significa que, en teoría, deberíamos esperar una static método que toma un objeto como parámetro y hace algo con él para que sea un poco menos bueno que el equivalente como instancia en ese mismo objeto. Sin embargo, una vez más, la diferencia es tan pequeña que si intentara medirla probablemente terminaría midiendo alguna otra decisión del compilador. (Especialmente porque la probabilidad de que esa referencia esté en un registro todo el tiempo también es bastante alta).
Las diferencias reales en el rendimiento se reducirán a si tiene objetos en la memoria artificialmente para hacer algo que naturalmente debería ser static, o está enredando cadenas de paso de objetos de formas complicadas para hacer lo que naturalmente debería ser una instancia.
De ahí el número 1. Cuando mantener el estado no es una preocupación, siempre es mejor estar static, porque eso es lo que static es para. No es un problema de rendimiento, aunque hay una regla general de jugar bien con las optimizaciones del compilador: es más probable que alguien se haya esforzado por optimizar los casos que surgen con el uso normal que los que surgen con un uso extraño.
Número 2. No importa. Hay una cierta cantidad de costo por clase para cada miembro en términos de la cantidad de metadatos que hay, la cantidad de código que hay en el archivo DLL o EXE real y la cantidad de código jitted que habrá. Esto es lo mismo si es una instancia o static.
Con el ítem 3, this
es como this
lo hace. Sin embargo, tenga en cuenta:
-
El
this
El parámetro se pasa en un registro particular. Al llamar a un método de instancia dentro de la misma clase, es probable que ya esté en ese registro (a menos que esté escondido y el registro se haya usado por alguna razón) y, por lo tanto, no se requiere ninguna acción para configurar elthis
a lo que necesita configurarse. Esto se aplica hasta cierto punto a, por ejemplo, que los dos primeros parámetros del método son los dos primeros parámetros de una llamada que realiza. -
Ya que quedará claro que
this
no es null, esto puede usarse para optimizar las llamadas en algunos casos. -
Ya que quedará claro que
this
no es null, esto puede hacer que las llamadas al método en línea sean más eficientes nuevamente, ya que el código producido para falsificar la llamada al método puede omitir algunos null-comprueba que podría necesitarlo de todos modos. -
Dicho eso null los cheques son baratos!
Vale la pena señalar que genérico static Los métodos que actúan sobre un objeto, en lugar de los métodos de instancia, pueden reducir algunos de los costos discutidos en http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-the-associated-overheads/ en el caso donde eso dado static no se llama para un tipo determinado. Como él dice, “Como un comentario al margen, resulta que los métodos de extensión son una excelente manera de hacer que las abstracciones genéricas sean más rentables”.
Sin embargo, tenga en cuenta que esto se relaciona solo con la instanciación de otros tipos utilizados por el método, que de otra manera no existen. Como tal, realmente no se aplica a muchos casos (algún otro método de instancia usó ese tipo, algún otro código en otro lugar usó ese tipo).
Resumen:
- Principalmente los costos de rendimiento de instancia vs. static están por debajo de insignificantes.
- Los costos que existen generalmente vendrán donde se abuse static por ejemplo o viceversa. Si no lo hace parte de su decisión entre static e ejemplo, es más probable que obtenga el resultado correcto.
- Hay casos raros en los que static Los métodos genéricos en otro tipo dan como resultado la creación de menos tipos, que los métodos genéricos de instancia, que pueden algunas veces tienen un pequeño beneficio que se utiliza con poca frecuencia (y “rara vez” se refiere a los tipos con los que se usa durante la vida útil de la aplicación, no con qué frecuencia se llama). Una vez que entienda de lo que está hablando en ese artículo, verá que es 100% irrelevante para la mayoría static-contra decisiones de instancia de todos modos. Editar: Y en su mayoría solo tiene ese costo con ngen, no con código jitted.
Editar: una nota sobre lo barato null-los cheques son (que reclamé arriba). Más null-las comprobaciones en .NET no comprueban null en absoluto, continúan con lo que iban a hacer con la suposición de que funcionará, y si ocurre una excepción de acceso, se convierte en una NullReferenceException
. Como tal, sobre todo cuando conceptualmente el código C # implica un null-marque porque está accediendo a un miembro de instancia, el costo si tiene éxito es en realidad cero. Una excepción serían algunas llamadas en línea, (porque quieren comportarse como si llamaran a un miembro de instancia) y simplemente presionan un campo para activar el mismo comportamiento, por lo que también son muy baratas y, de todos modos, a menudo se pueden omitir. (por ejemplo, si el primer paso del método implicaba acceder a un campo tal como estaba).
Cuando mantener el estado no es una preocupación (no se requieren campos o propiedades), ¿es siempre mejor usar un static ¿clase?
Yo diría que sí. Como declarando algo static
declaras un intención de ejecución sin estado (no es obligatorio, pero es una intención de algo que uno esperaría)
Donde hay un número considerable de estos static clases (digamos 100, por ejemplo, con un número de static métodos cada uno) ¿afectará esto el rendimiento de ejecución o el consumo de memoria de manera negativa en comparación con el mismo número de clases de instancia?
No lo crea, a menos que esté seguro de que static las clases son De Verdad stetless, porque si no es fácil estropear las asignaciones de memoria y tener pérdidas de memoria.
Cuando el [this] la palabra clave se utiliza para llamar a otro método dentro de la misma clase de instancia, ¿todavía se produce la resolución de la instancia?
No estoy seguro sobre esta punto (este es un detalle puramente de implementación de CLR), pero piense que sí.
Comentarios y valoraciones
Si te apasiona la programación, tienes la opción de dejar un artículo acerca de qué le añadirías a este ensayo.