Rendimiento del uso de métodos estáticos vs creación de instancias de la clase que contiene los métodos

StackOverflow https://stackoverflow.com/questions/202631

Pregunta

Estoy trabajando en un proyecto en C #. El programador anterior no conocía la programación orientada a objetos, por lo que la mayoría del código está en archivos enormes (estamos hablando de 4-5000 líneas) repartidas en decenas y, a veces, cientos de métodos, pero solo una clase. Refactorizar un proyecto de este tipo es una tarea enorme, por lo que, por ahora, he aprendido a vivir con él.

Cada vez que se usa un método en uno de los archivos de código, la clase se crea una instancia y luego se llama al método en la instancia del objeto.

¿Me pregunto si existen penalizaciones de rendimiento notables al hacerlo de esta manera? ¿Debo hacer todos los métodos estáticos " por ahora " y, lo más importante, ¿se beneficiará la aplicación de alguna manera?

¿Fue útil?

Solución

Desde aquí , una llamada estática es de 4 a 5 veces más rápida que construir una instancia cada vez que llamas a un método de instancia. Sin embargo, aún estamos hablando de decenas de nanosegundos por llamada, por lo que es poco probable que note algún beneficio a menos que tenga bucles muy ajustados llamando a un método millones de veces, y podría obtener el mismo beneficio construyendo una sola instancia fuera ese bucle y reutilizándolo.

Como tendrías que cambiar cada sitio de llamadas para usar el nuevo método estático, probablemente estés mejor gastando tu tiempo en refactorizar gradualmente.

Otros consejos

He resuelto un problema similar en el que trabajo. El programador anterior a mí creó una clase de controlador donde todas las funciones de BLL se descargaron.

Estamos rediseñando el sistema ahora y hemos creado muchas clases de controladores en función de lo que se supone que deben controlar, por ejemplo

UserController, GeographyController, ShoppingController ...

Dentro de cada clase de controlador tienen métodos estáticos que hacen llamadas a la caché o al DAL usando el patrón de singleton.

Esto nos ha dado 2 ventajas principales. Es un poco más rápido (alrededor de 2 a 3 veces más rápido, pero hablaba de nanosegundos aquí; P). La otra es que el código es mucho más limpio

es decir

ShoppingController.ListPaymentMethods()

en lugar de

new ShoppingController().ListPaymentMethods()

Creo que tiene sentido usar métodos o clases estáticas si la clase no mantiene ningún estado.

Depende de qué más contiene ese objeto, si el " objeto " es solo un montón de funciones, entonces probablemente no sea el fin del mundo. Pero si el objeto contiene un montón de otros objetos, la instanciación llamará a todos sus constructores (y destructores, cuando se elimine) y puede obtener una fragmentación de la memoria, etc.

Dicho esto, no parece que el rendimiento sea tu mayor problema en este momento.

Tienes que determinar los objetivos de la reescritura. Si quieres tener un buen comprobable, extensible y amp; código OO mantenible, entonces podría intentar usar objetos y sus métodos de instancia. Después de todo esto, estamos hablando de programación orientada a objetos, no de programación orientada a clases.

Es muy sencillo falsificar y / o simular objetos cuando define clases que implementan interfaces y ejecuta métodos de instancia. Esto hace que las pruebas de unidad completas sean rápidas y efectivas.

También, si va a seguir buenos principios de OO (vea SOLID en http: //en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29 ) y / o use patrones de diseño, seguramente realizará una gran cantidad de desarrollos basados ??en interfaces, basados ??en instancias, y no usará muchos métodos estáticos.

En cuanto a esta sugerencia:

  
    

Me parece una tontería crear un objeto JUSTO para que puedas llamar a un método que     Aparentemente no tiene efectos secundarios en el objeto (de su descripción asumo esto).

  

Veo esto mucho en las tiendas de dot net y para mí esto viola la encapsulación, un concepto clave de OO. No debería poder saber si un método tiene efectos secundarios por si el método es estático o no. Además de romper la encapsulación, esto significa que tendrá que cambiar los métodos de estática a instancia si / cuando los modifique para tener efectos secundarios. Le sugiero que lea el principio Abierto / Cerrado para este y vea cómo el enfoque sugerido, citado anteriormente, funciona con eso en mente.

Recuerde que el viejo castaño, 'la optimización prematura es la raíz de todo mal'. Creo que en este caso, esto significa que no debes saltar a través de aros usando técnicas inapropiadas (es decir, programación orientada a clases) hasta que sepas que tienes un problema de rendimiento. Aún así, depure el problema y busque el más apropiado.

Los métodos estáticos son mucho más rápidos y utilizan menos memoria. Existe la idea errónea de que es un poco más rápido. Es un poco más rápido siempre y cuando no lo pongas en bucles. Por cierto, algunos bucles parecen pequeños pero en realidad no lo son porque la llamada al método que contiene el bucle también es otro bucle. Puedes notar la diferencia en el código que realiza las funciones de renderizado. Lamentablemente, mucho menos memoria es cierta en muchos casos. Una instancia permite compartir fácilmente información con métodos hermanos. Un método estático le pedirá la información cuando la necesite.

Pero al igual que en la conducción de automóviles, la velocidad trae responsabilidad. Los métodos estáticos usualmente tienen más parámetros que su contraparte de instancia. Debido a que una instancia se ocuparía del almacenamiento en caché de las variables compartidas, sus métodos de instancia se verán más bonitos.

ShapeUtils.DrawCircle(stroke, pen, origin, radius);

ShapeUtils.DrawSquare(stroke, pen, x, y, width, length);

VS

ShapeUtils utils = new ShapeUtils(stroke,pen);

util.DrawCircle(origin,radius);

util.DrawSquare(x,y,width,length);

En este caso, cuando las variables de instancia son utilizadas por todos los métodos la mayor parte del tiempo, los métodos de instancia valen la pena. Las instancias NO SON SOBRE EL ESTADO, se trata de COMPARTIR aunque el ESTADO COMÚN es una forma natural de COMPARTIR, NO SON LO MISMO. La regla general es esta: si el método está estrechamente relacionado con otros métodos, se aman tanto que cuando se llama uno, el otro también debe llamarse y probablemente compartan la misma taza de agua. -, debe hacerse instancia. Traducir métodos estáticos a métodos de instancia no es tan difícil. Solo necesita tomar los parámetros compartidos y ponerlos como variables de instancia. Al revés es más difícil.

O puede crear una clase proxy que enlace los métodos estáticos. Si bien puede parecer que es más ineficiente en teoría, la práctica cuenta una historia diferente. Esto se debe a que siempre que necesite llamar a DrawSquare una vez (o en un bucle), vaya directamente al método estático. Pero cada vez que lo uses una y otra vez junto con DrawCircle, usarás el proxy de instancia. Un ejemplo son las clases System.IO FileInfo (instancia) vs File (estático).

Los métodos estáticos son comprobables. De hecho, incluso más comprobable que una vez. El método GetSum (x, y) sería muy comprobable no solo para la prueba unitaria sino también para la prueba de carga, la prueba integrada y la prueba de uso. Los métodos de instancia son buenos para las pruebas de unidades, pero son horribles para todas las demás pruebas (lo que importa más que las pruebas de unidades por cierto), es por eso que tenemos muchos errores en estos días. Lo que hace que TODOS los métodos no se puedan probar son parámetros que no tienen sentido como (Sender s, EventArgs e) o estados globales como DateTime.Now. De hecho, los métodos estáticos son tan buenos para la capacidad de prueba que se ven menos errores en el código C de una nueva distribución de Linux que en su programador OO promedio (está lleno de *** lo sé).

Creo que has respondido parcialmente a esta pregunta de la forma en que la hiciste: ¿hay alguna notable penalización de rendimiento en el código que tienes?

Si las penalizaciones no son perceptibles, no es necesario que hagas nada en absoluto. (Aunque no hace falta decir que la base de código se beneficiaría dramáticamente de un refactor gradual en un modelo de OO respetable).

Supongo que lo que digo es que un problema de rendimiento es solo un problema cuando te das cuenta de que es un problema.

Me parece una tontería crear un objeto JUSTO, así que puedes llamar a un método que aparentemente no tiene efectos secundarios en el objeto (de tu descripción supongo que esto). Me parece que un mejor compromiso sería tener varios objetos globales y solo usarlos. De esa manera, puede colocar las variables que normalmente serían globales en las clases apropiadas para que tengan un alcance un poco menor.

Desde allí puedes mover lentamente el alcance de estos objetos para que sean cada vez más pequeños hasta que tengas un diseño de POO decente.

De nuevo, el enfoque que probablemente utilizaría I es diferente;).

Personalmente, probablemente me concentraría en las estructuras y las funciones que operan en ellas y trataré de convertirlas en clases con miembros poco a poco.

En cuanto al aspecto de rendimiento de la pregunta, los métodos estáticos deberían ser un poco más rápidos (pero no mucho), ya que no implican construir, pasar y deconstruir un objeto.

No es válido en PHP,
El método de objeto es más rápido:
http://www.vanylla.it/tests/static-method-vs -object.php

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top