En las décadas de los 70, 80 e incluso 90, las máquinas tenían muy poca memoria RAM (unos pocos kilobytes al principio) y una velocidad de CPU de pocos megahertz (8 MHz en el caso del Intel 8086). Un procesador Intel i7 de hoy en día, supera los 5GHz. Se han superado las prestaciones en muchos órdenes de magnitud. Sin embargo, hoy se sigue educando a los futuros programadores para que escriban un código óptimo en consumo de CPU y memoria, como si las máquinas tuvieran las prestaciones de hace 30 años.
Cuando las máquinas tenían pocas prestaciones en cuanto a hardware, los compiladores también eran muy limitados comparados con los de hoy en día. Los lenguajes de programación más usados eran de bajo nivel (sobre todo se usaba Ensamblador y después C) y los programadores tenían que gestionar la memoria y optimizar al máximo su código, porque ninguna otra herramienta lo iba a hacer por ellos. En la década de los 80, los compiladores empezaban a implementar suficientes optimizaciones, como para que el lenguaje Ensamblador fuese perdiendo popularidad. Cuando aparecieron máquinas virtuales de proceso como la JVM, los compiladores experimentaron una revolución, eran capaces de optimizar el código mejor que los propios programadores usuarios del lenguaje (Java, por ejemplo). Cualquier optimización que uno pretenda hacer en Java para ganar unos pocos ciclos de CPU, es insignificante en términos de velocidad y a veces incluso contraproducente. El compilador lo hará mejor. Otra cosa es cambiar el diseño de los algoritmos para que en lugar de tener una complejidad cuadrática, pasen a ser logarítmicos, esto sí puede tener un impacto notable si estamos trabajando con cantidades de datos ingentes (si estamos hablando de buscar en 1000 registros en memoria, tampoco se va a notar nada).
¿Merece la pena intentar escribir código eficiente en consumo de CPU y memoria hoy en día? Hay algunos casos en los que sí, pero son muy pocos. Aquí algunos:
Si no eres David Brevik, ni estás trabajando en el siguiente browser más rápido del mercado, ¡olvídate de intentar optimizar tu código! Porque el código que “parece óptimo”, es menos legible, costará más trabajo entenderlo. Digo que “parece óptimo”, porque ni siquiera medimos si hay ganancia. El primer paso para conseguir código óptimo es medir, hacer comparativas (benchmarks) para saber de forma empírica cuál es el que mejor rinde. Cuando diseñaron Chrome, seguro que no dejaron el código que de primeras les parecía más rápido, sino que hicieron comparativas midiendo consumos. Si de verdad te preocupa el rendimiento, utiliza métricas, no ofusques el código solo por la intuición de que estás ganando en velocidad (ya que seguramente no es cierto).
Recuerdo que esta frase se la escuché por primera vez al bueno de Esteban Manchado. El cuello de botella, hoy en día, está en la latencia de la red y del disco. Una petición de lectura mediante una API REST va a tardar más de 100 milisegundos, fácilmente serán 200, 300 o más. Imagina que el backend trae 10.000 registros de la base de datos y luego en código hacemos alguna operación que filtra, ordena o de alguna forma recorre esos registros, consumiendo CPU antes de devolverlos por la red ¿Qué importancia tiene la optimización de nuestro código en esta operación en memoria?.
|
|
Este código es un pequeño experimento para ver lo que tardan en mi pc distintas operaciones. Recorrer un array de 10.000 elementos y leer una propiedad de cada elemento (lo que sería hacer un filtrado simple), tarda menos de 1 milisegundo. Ordenar el array con merge sort tarda unos 50 milisegundos y ordenarlo con bubble sort tarda unos 1000 milisegundos ¿Tiene sentido que intentes optimizar el código que filtra datos en memoria? Es evidente que no. Sin embargo, tiene sentido entender de complejidad de los algoritmos para darse cuenta de que operaciones cuadráticas como el bubble sort tienen un impacto notable, aunque de nuevo dependerá del volumen de datos que estamos moviendo. Si son 200 registros (y no se esperan que aumente el orden de magnitud), no te molestes.
A veces, escribimos código oscuro en nombre de la optimización, por ejemplo, para convertir un entero en un string:
let text = number + "";
Aun cuando es mucho más explícito lo siguiente:
let text = number.toString();
¿Cuántos miles o millones de veces tendría que ejecutarse esa conversión para que llegásemos a notar algún tipo de diferencia de rendimiento?, ¿lo notaríamos alguna vez?
Antes de la aparición del motor V8, la forma de escribir JavaScript podía tener diferencias notables en aplicaciones web que realizasen una cantidad considerable de cómputo. El lenguaje estaba en plena evolución y los navegadores también, por lo que en determinados casos valía la pena conocer los hacks de rendimiento del lenguaje en cada navegador. Hoy en día, no me encuentro con casos en los que siga haciendo falta “optimizar” en JavaScript, sobre todo porque cada vez más programamos con ES6 o superiores, con TypeScript y con otros lenguajes que terminan compilando a JavaScript de una forma optimizada.
El código es más fácil de entender cuanto mejor refleja la intención de quien lo escribió, para lo cual se requiere ser muy explícitos escribiéndolo.
Es preferible programar para que el código sea legible que para que sea óptimo, aunque no está de más conocer la complejidad de los algoritmos que podemos usar en librerías, para que escojamos el mejor. Por desgracia, hay que escoger entre legible y óptimo, porque son características bastante excluyentes.
Cuando no estamos seguros del volumen de cómputo que a futuro podemos necesitar, yo prefiero quedarme con el código que es suficientemente bueno para hoy, aunque mañana se quede corto. Si tengo la idea de que es muy probable que haya que mejorar el rendimiento en el futuro, prefiero anotarlo en el documento de gestión de deuda técnica y dejar el código simple. Prefiero un enfoque lean con buena planificación y estrategia, que la sobreingenieria prematura.
¿Quieres más? te invitamos a suscribirte a nuestro boletín para avisarte cada vez que recopilemos contenido de calidad que compartir.
Si disfrutas leyendo nuestro blog, ¿imaginas lo divertido que sería trabajar con nosotros? ¿te gustaría?
Pero espera 🖐 que tenemos un conflicto interno. A nosotros las newsletter nos parecen 💩👎👹 Por eso hemos creado la LEAN LISTA, la primera lista zen, disfrutona y que suena a rock y reggaeton del sector de la programación. Todos hemos recibido newsletters por encima de nuestras posibilidades 😅 por eso este es el compromiso de la Lean Lista