¿Cómo evito la "intuición de mala optimización del desarrollador"?

22

Vi en un artículo que presentó esta declaración:

Los desarrolladores adoran optimizar el código y con buenas razones. Es muy satisfactorio y divertido. Pero saber cuándo optimizar es mucho más importante. Desafortunadamente, los desarrolladores generalmente tienen una intuición horrible sobre dónde estarán realmente los problemas de rendimiento en una aplicación.

¿Cómo puede un desarrollador evitar esta mala intuición? ¿Existen buenas herramientas para encontrar qué partes de su código realmente necesitan optimización (para Java)? ¿Conoces algunos artículos, consejos o buenas lecturas sobre este tema?

Mona
fuente
1
Esto se reduce a "¿Cómo evito [depender] de las intuiciones [al tomar decisiones]?" Simple: se verifica con datos concretos y datos. Entonces, en el caso de la optimización, desde la perspectiva de un desarrollador: usted es un punto de referencia.
haylem

Respuestas:

44
  • Use un buen perfilador para identificar métodos caros.
  • Documente cuánto tiempo duraron los puntos calientes.
  • Escriba una implementación más rápida de los puntos calientes.
  • Documente cuánto tiempo tardan los puntos calientes, con suerte ya no los convertirá en puntos calientes.

Esencialmente, debe poder demostrar a los demás dónde estaba el problema y que este cambio hizo que desapareciera.

No poder demostrar una mejora, califica, en mi opinión personal, para la reversión inmediata a la versión original.

Robert Harvey
fuente
51
O para decirlo de manera más simple: "Para evitar una mala intuición de optimización, no use la intuición. Mida".
Kyralessa
66
Es por eso que la suya es una respuesta y la mía es solo un comentario. : P
Kyralessa
2
@Thomas, si juegas con la legibilidad y la facilidad de mantenimiento, no estás viendo exactamente los problemas de rendimiento, ¿verdad?
3
@ Thomas, no estoy de acuerdo. Incluso dentro de las especificaciones, debe volver a probar el nuevo código a fondo. Esto no es necesario para el código anterior. Revertir.
2
@ Thorbjørn Después de ajustar el rendimiento, también debe volver a probar el nuevo código a fondo. Ahorrar tiempo o memoria no tiene sentido si introdujo un defecto.
Thomas Owens
10

La única forma de saber dónde optimizar es perfilar su código. En lugar de hacer cambios que cree que proporcionarán un beneficio, sepa con certeza dónde está el código de peor desempeño y comience allí.

Java hace que esto sea bastante fácil con la herramienta VisualVM , que se ha incluido con versiones recientes del Kit de desarrollo de Java (JDK). La idea es averiguar qué métodos se llaman más y en qué métodos pasa la mayor parte de su tiempo, tanto en su código como en bibliotecas externas. También puede obtener datos de rendimiento en la recolección de basura para que pueda ajustar su recolector y ajustar el espacio de almacenamiento dinámico mínimo / máximo requerido por su aplicación.

Thomas Owens
fuente
VisualVM no está en JRE, solo en JDK.
1
@ Thorbjørn Ravn Andersen Buena llamada. Debo aclarar. Sin embargo, si está desarrollando Java, generalmente tiene el JDK instalado (aunque puede estar ejecutando OpenJDK o similar; no sé si estos vienen con VisualVM).
Thomas Owens
1
Con mucha frecuencia cambio de espacios de trabajo en Eclipse, que por defecto es el JRE que lanzó Eclipse. Como es mucho más fácil instalar JRE que JDK, hemos migrado lentamente a un proceso de compilación de hormigas que incluye el compilador Eclipse y, por lo tanto, puede ejecutarse en el JRE simple. Por lo tanto, en estos días se pueden realmente hacer el trabajo real sin el JDK. VisualVM se puede descargar por separado, lo que facilita su uso con un Java Versino dado, ya que en Windows, los JVM de 64 bits no pueden conectarse a JVM de 32 bits y viceversa.
9

Como cualquiera aquí está hablando de perfiladores, me centraré en esta parte de la pregunta.

¿Cómo puede un desarrollador evitar esta mala intuición?

Tú. hacer. no. En cambio, nunca optimizas desde el principio .
Repítelo una y otra vez, ya que es un mantra religioso.

Te encontrarás haciendo eso y descubrirás que no deberías haberlo hecho.
Y luego otra vez.
Y otra vez.

La optimización temprana es uno de los pecados capitales de los programadores .

Las herramientas y las cosas son parte de la optimización posterior, que es un oficio establecido .

ZJR
fuente
Optimización temprana de "código complicado", seguro. La elección de algoritmos y / o estructuras de datos que se ajusten a su problema y (con su carga de procesamiento esperada) tengan buenas características de rendimiento es algo que debe hacerse antes de comenzar a escribir código.
Vatine
@Vatine Sí, he estado allí. No, solo no lo hagas. Haga lo que corresponda a su mapa mental del problema en cuestión. Que podría ser el algoritmo mas potente , y le deseo eso, no tiene por qué.
ZJR
me parece como el principio de YAGNI: ¡NO lo vas a necesitar!
EL Yusubov
7

Estas herramientas se llaman perfiladores . Puede usarlos para medir qué parte (s) de su programa tardan más en ejecutarse, por lo tanto, dónde enfocar sus esfuerzos de ajuste.

Es igualmente importante medir nuevamente después de los cambios, para verificar que sus cambios tengan el efecto deseado.

Péter Török
fuente
5

Mire también la cantidad de memoria que usa su programa, no solo su velocidad o tiempo de ejecución.

Muchos codificadores que trabajan con lenguajes recolectados de basura, como Java, tienen la impresión errónea de que la recolección de basura evita pérdidas de memoria. Ese no es el caso. Si mantiene una referencia a un objeto que ya no necesita, no se recopilará y, por lo tanto, se filtrará.

¡He visto aplicaciones web de Java que tenían tanta fuga que harían que su servidor se quedara sin espacio de intercambio!

Si utiliza un generador de perfiles de tiempo de ejecución y algún tipo de generador de perfiles de memoria, aprenderá a escribir código más ágil e intuitivo de forma intuitiva. Esto tiene el efecto de que es más probable que su código se ejecute rápidamente en el primer intento.

Mike Crawford
fuente
1

mi remedio es comenzar obteniendo respuestas claras a dos preguntas:

  1. Cómo medir el rendimiento (por ejemplo, medir el tiempo de carga de datos )
  2. cuál es el valor objetivo (p. ej., las cargas de datos en 3 segundos o menos con un 95% de confianza )

Aprendí el truco anterior de los chicos del equipo de tigres que una vez fueron invitados a guardar un lanzamiento roto de nuestro producto. Ese lanzamiento se rompió por razones de rendimiento, podría hacer que la compañía pierda clientes estratégicos, lo que justificó la participación de los tigres (por cierto, bastante caro). Me asignaron ayudarlos a aclarar los detalles del proyecto; También usé esto como una oportunidad para aprender un poco o dos sobre el rendimiento.

mosquito
fuente
1

Lo que he encontrado es el mejor antídoto para la optimización prematura es este método .

Una vez que lo ha usado para acelerar algún código (como en este ejemplo ), se convierte en una adicción propia, y comprende que el primer principio de ajuste de rendimiento no es ajustar el código, sino encontrar el problema .

La optimización real es la optimización prematura, ya que cazar para alimentar a su familia es disparar latas. Se trata de encontrar la cantera.

Mike Dunlavey
fuente
1
Y desafortunadamente, solo puede llevar 200 libras a su familia, así que no dispare ardillas todo el día.
Jordania
1

Antigua pregunta, pero ofreceré esta respuesta que difiere considerablemente de las demás.

Las grandes oportunidades para aumentar el rendimiento provienen del procesamiento paralelo. Intente diseñar su código para aprovechar múltiples hilos. (Incluso si, por simplicidad, no lo haces en la versión 1). Pocas conjeturas o intuiciones necesarias.

Cualquier otra cosa es la optimización prematura y requiere su intuición, que a menudo está mal.

user949300
fuente
Muy buen punto. En el pasado, podría contar con procesadores cada vez más rápidos cada pocos años. Ahora solo debe esperar que haya más procesadores.
JimmyJames
0

Su intuición puede mejorar con el tiempo. Lo descartaría, tal vez un poco controvertido, pero durante muchos años de usar VTune y CodeAnalyst y ahora CodeXL, diría que soy mucho más preciso en mis intuiciones que antes sobre dónde estarán los puntos calientes, al menos para el punto donde ya no estoy completamente desprevenido cuando perfilo un código. Eso no significa que intente optimizar las cosas a ciegas.

La elaboración de perfiles ha aumentado mi dependencia de los perfiladores, no la ha disminuido. Solo digo que puedo anticipar más fácilmente cuáles serán los resultados de la creación de perfiles hasta cierto punto y, además, eliminar con éxito los puntos críticos y mejorar el tiempo que lleva completar la operación del usuario final sin tener que apuñalar a ciegas en la oscuridad y faltar (algo que puede hacerlo incluso cuando usa un generador de perfiles hasta que comience a comprender no solo cuáles son los puntos de acceso, sino también por qué exactamente son puntos de acceso con respecto a, por ejemplo, errores de caché).

Sin embargo, no fue hasta que comencé a usar perfiladores que comencé a mejorar esa intuición. Una de las razones es porque si está bien familiarizado con su código, sus corazonadas pueden ser correctas con respecto a los puntos calientes más grandes y obvios, pero no todas las sutilezas intermedias. Naturalmente, si tiene una operación de finalización de usuario que tarda una hora en completarse y hay un algoritmo de complejidad cuadrática que procesa una entrada que abarca cien mil elementos, es probable que pueda salir rico jugando sus ahorros de toda la vida con la idea de que es la complejidad cuadrática algoritmo en falta aquí. Pero eso no le da una idea detallada o, por ejemplo, le permite saber exactamente lo que no está contribuyendo al momento.

Hay tanto valor cuando comienzas a crear perfiles y ver dónde todas las cosas que creías que podrían haber sido un gran contribuyente de tiempo no estaban contribuyendo mucho tiempo; no las enormes fuentes obvias de ineficiencias, sino las que sospechaba que podrían haber sido ligeramente ineficientes, pero, después de la elaboración del perfil, al darse cuenta de que apenas contribuyeron en ningún momento. Y ahí es potencialmente donde obtienes la visión más intuitiva es que te muestran mal en todas esas áreas sutiles donde no es obvio exactamente cuánto tiempo se está gastando.

La intuición humana más allá de la complejidad algorítmica obvia a menudo comenzará de manera incorrecta porque lo que es eficiente para la máquina y lo que es eficiente para la mente humana son muy diferentes. Al principio, no resulta tan intuitivo pensar en las jerarquías de memoria que van desde los registros a la memoria caché de la CPU a la DRAM al disco. No resulta intuitivo pensar que la aritmética redundante puede ser más rápida que hacer más ramificaciones o accesos a la memoria de una tabla de búsqueda para omitir algún trabajo de procesamiento. Tendemos a pensar en términos de cuánto trabajo hay que hacer al descontar cosas como el costo de tomar decisiones y las cargas y tiendas de memoria. Lo que es eficiente para el hardware es a menudo muy intuitivo en formas que romperán todos sus supuestos humanos comenzando,

Donde mejorar esa intuición puede ayudar, a través del perfil, es el diseño de la interfaz . Los diseños de interfaz son muy costosos de cambiar en retrospectiva, y los costos aumentan en proporción al número de lugares que dependen de esa interfaz. Cuando comience a mejorar su intuición, puede comenzar a diseñar mejor las interfaces la primera vez de manera que deje espacio para la optimización futura sin costosos cambios de diseño. Sin embargo, una vez más, esa intuición es algo que generalmente se desarrolla y continúa desarrollándose indefinidamente, siempre teniendo ese perfilador a mano.


fuente
0

Los perfiladores ayudan a corregir la mala intuición cuando se trata de código. Dada la cantidad de hardware que predice en estos días, no es humanamente práctico predecir el rendimiento de su código, pero eso aún era cierto en la época de Knuth, hace tantas décadas, quien abogó por que los perfiladores deberían incluirse como parte de las herramientas estándar para el desarrollo para solucionar el problema. naturaleza "tonta de centavo y libra" de los desarrolladores. Pero voy a tomar una ruta muy diferente con esta respuesta dado lo exhaustivas que son las respuestas en otros aspectos y decir que la comprensión del usuario final es la otra "solución".

He sido testigo, en mi experiencia personal, de un desarrollador particularmente brillante (pero con grandes puntos ciegos sobre cómo los usuarios realmente usan el software) optimizando un algoritmo de subdivisión con un perfilador en mano (uno muy bueno, costoso y completo: Intel VTune con gráfico de llamadas el muestreo en la parte superior de los perfiladores de GPU) para mallas logra resultados sorprendentes con miles de millones de facetas en la GPU al subdividir primitivas simples como cubos con 6 polígonos de jaula / entrada. Excepto que lo ajustó y ajustó contra ese caso de prueba que era diferente a cualquier caso de uso del mundo real (los usuarios no quieren mil millones de facetas en un cubo subdividido que comienza a parecerse a una esfera perfecta, sus entradas de subdivisión tienden a ser cosas como personajes y vehículos y otras entradas complejas).

Curiosamente, llegué más lejos con un cerebro medio funcional como él y sin doctorado en mi carrera por la simple razón de que entendía lo que los usuarios querían, lo que el marketing quería, lo que los diseñadores querían. Realmente no puedo enfatizar lo suficiente lo útil que es ser capaz de ponerse en la mentalidad y los zapatos del usuario y mirar su software y lo que debe hacer como usuarios reales mientras se esfuerza por divorciarse de los esfuerzos que pone para construir lo que construiste y mirarlo con un par de ojos nuevos. Incluso me encontré con el desarrollador anterior que esto es algo imposible de hacer; él pensaba que era culpable de tener un tipo de ego similar al que tienen todos los desarrolladores con conocimientos técnicos pero ajenos al usuario, y constantemente he demostrado que está equivocado cuando los usuarios y diseñadores acuden a mí para hablar sobre exactamente qué hacer. Eso suena muy egoísta, pero lo equilibraré con el descargo de responsabilidad de que no soy un programador tan brillante, pero entiendo lo que quieren los usuarios y diseñadores, y eso me hizo particularmente favorecido en mi campo donde esto parecía ser particularmente raro calidad por alguna razón. Como programadores, probablemente estemos más acostumbrados a realizar pruebas que a comprender y socializar con personas comunes y no técnicas.

Por lo tanto, hay perfiles y mediciones adecuadas, pero también existe la necesidad fundamental de asegurarse de que está midiendo una operación con el tipo de entradas que los usuarios del mundo real realmente proporcionarán a la aplicación. De lo contrario, incluso puede tener VTune o CodeAnalyst o gprof o cualquier otro generador de perfiles en la mano y aún así, mientras intenta optimizar los puntos de acceso contra lo que podría parecer un caso de prueba normal para el desarrollador pero oscuro para los usuarios, termine pesimizando el caso de uso común a favor de algún caso de uso oscuro que pocos usuarios, si alguno, consideran aplicar.

Al final del día, todas las impracticabilidades que tendemos a llevar como desarrolladores se pueden equilibrar con el martillo de hierro de lo que hace a los usuarios realmente felices sin resolver el hambre mundial, y la necesidad práctica de obtener dinero para que podamos pagar el alquiler o comprar cerveza o mira mujeres desnudas o lo que quieras / necesites hacer. Todo lo demás está trabajando potencialmente en contra de esa necesidad comercial fundamental, y cualquier desarrollador tan noble, tan heroico, para olvidar que se trata de ganar dinero y, en última instancia, satisfacer a los usuarios para que paguen, podría ser bueno para bajar a la tierra y apague el modo dios creando mundos virtuales a favor de la necesidad del mundo real de simplemente enviar y obtener algo de dinero para comida. Podemos perdernos en métricas y prácticas de software, pero fundamentalmente '

Dragon Energy
fuente