¿Qué lenguajes de programación consumen menos electricidad?
¿Pueden los datos sobre el uso de la energía decirnos algo sobre la calidad de nuestros lenguajes de programación?
El año pasado, un equipo de seis investigadores portugueses de tres universidades diferentes decidió investigar esta cuestión y acabó publicando un documento titulado «Energy Efficiency Across Programming Languages». Ejecutaron las soluciones a 10 problemas de programación escritos en 27 lenguajes diferentes, mientras monitorizaban cuidadosamente cuánta electricidad utilizaba cada uno, así como su velocidad y uso de la memoria.
Específicamente, utilizaron 10 problemas del Computer Language Benchmarks Game, un proyecto de software libre para comparar el rendimiento que incluye un conjunto estándar de problemas algorítmicos sencillos, así como un marco para ejecutar pruebas. (Antes se conocía como «The Great Computer Language Shootout»). «Esto nos permitió obtener un conjunto comparable, representativo y extenso de programas… junto con las opciones de compilación/ejecución y las versiones del compilador».
Fue importante ejecutar una variedad de pruebas de referencia porque, en última instancia, sus resultados variaban dependiendo de la prueba que se realizara. Por ejemplo, en general el lenguaje C resultó ser el más rápido y también el más eficiente energéticamente. Pero en la prueba de referencia que consistía en escanear una base de datos de ADN en busca de una secuencia genética concreta, Rust fue el más eficiente energéticamente, mientras que C quedó en tercer lugar.
Incluso en esa misma prueba, el «mejor» lenguaje depende de cuál sea tu criterio. Para esa prueba, C también resultó ser sólo el segundo lenguaje más rápido (de nuevo, situándose por detrás de Rust). Sin embargo, Rust pierde nueve posiciones si los resultados se ordenan por el uso de la memoria. Y aunque Fortran fue el segundo lenguaje más eficiente energéticamente para esta prueba, también cayó seis posiciones cuando los resultados se ordenaron por tiempo de ejecución.
Un lenguaje más rápido no siempre es el más eficiente energéticamente.
Los investigadores señalan que «siguieron estrictamente» las directrices del proyecto CLBG sobre las versiones del compilador y las mejores banderas de optimización. El consumo de energía se midió utilizando una herramienta de Intel -la herramienta Running Average Power Limit- con cada programa ejecutado no sólo una vez, sino 10 veces, «para reducir el impacto de los arranques en frío y los efectos de la caché, y poder analizar la consistencia de las mediciones y evitar los valores atípicos.» (Por esta razón, informan de que «los resultados medidos son bastante consistentes»). Para mayor consistencia, todas las pruebas se realizaron en un ordenador de sobremesa que ejecutaba Linux Ubuntu Server 16.10 (versión del kernel 4.8.0-22-generic), con 16 GB de RAM y una CPU Haswell Intel Core i5-4460 a 3,20 GHz.
En su documento, los investigadores destacan algunos resultados interesantes.
«Lisp, de media, consume 2.27 veces más energía (131,34J) que C, mientras que tarda 2,44 veces más en ejecutarse (4926,99ms), y necesita 1,92 veces más memoria (126,64Mb) en comparación con Pascal».
También compararon los resultados de los lenguajes compilados frente a los interpretados (con una categoría separada para los lenguajes que se ejecutan en máquinas virtuales). El artículo también incluye una comparación por separado de los diferentes paradigmas de programación, incluyendo la programación funcional y la imperativa, además de la programación orientada a objetos y los scripts.
¿Es la rapidez más ecológica?
El artículo analiza la suposición común de que un programa más rápido siempre utilizará menos energía, señalando que no es tan simple como la ley de la física que dice E(nergía) = T(tiempo) x P(energía). Esto se debe, en parte, a que la energía no se gasta a un ritmo constante, señalan los investigadores, lo que sugiere que puede afectar al trabajo de otros investigadores que estudian si el tiempo de ejecución de un programa afecta a su consumo de energía. («Las conclusiones sobre esta cuestión son a veces divergentes…») En una de sus pruebas de referencia, un programa Chapel tardó un 55% menos en ejecutarse que un programa equivalente escrito en Pascal, y sin embargo ese programa Pascal consumió un 10% menos de energía.
Así que, aunque sigue existiendo la creencia común de que el consumo de energía disminuye cuando los programas se ejecutan más rápido, los investigadores afirman de forma inequívoca que «un lenguaje más rápido no siempre es el más eficiente desde el punto de vista energético»
Puede ser una pregunta difícil de responder, ya que el consumo de energía se ve afectado por muchos factores (incluida la calidad del compilador y las bibliotecas que se utilizan). Pero, en última instancia, los investigadores fueron capaces de desglosar el consumo de energía en función de si lo consumía la CPU o la DRAM, y llegaron a la conclusión de que la mayor parte de la energía (alrededor del 88%) la consumía la CPU, por término medio, tanto si el programa de referencia se compilaba como si se interpretaba o se ejecutaba en una máquina virtual.
Es interesante observar que los lenguajes interpretados mostraban una variación ligeramente superior, ya que la CPU consumía a veces hasta el 92%.90 por ciento de la energía o tan sólo el 81,57 por ciento.
Después de estudiar sus resultados, los investigadores también llegaron a la conclusión de que la relación entre el uso máximo de la DRAM y el consumo de energía «es casi inexistente».
La investigación proporciona algunas ideas más sobre la eterna pregunta: ¿es lo más rápido más ecológico? Sí, es cierto que «los cinco lenguajes más eficientes desde el punto de vista energético mantienen su rango cuando se ordenan por tiempo de ejecución y con diferencias muy pequeñas tanto en los valores de energía como de tiempo»
De hecho, para nueve de cada 10 problemas de referencia, la puntuación más alta (tanto para la velocidad como para la eficiencia energética) provino de uno de los tres lenguajes más rápidos y eficientes desde el punto de vista energético en general, lo que no sorprendió a los investigadores. «Es sabido que estos tres primeros lenguajes (C, C++ y Rust) son conocidos por estar fuertemente optimizados y ser eficientes en cuanto a rendimiento de ejecución, como también muestran nuestros datos»
Pero no se ve el mismo orden cuando se clasifican los otros 24 lenguajes por su tiempo de ejecución que cuando se clasifican por eficiencia energética. «Sólo cuatro lenguajes mantienen el mismo rango de energía y tiempo (OCaml, Haskel, Racket y Python), mientras que el resto se barajan por completo.»
Incluso en las pruebas de referencia individuales, hay casos en los que los lenguajes de rendimiento rápido no son los más eficientes energéticamente.
Las ventajas de los lenguajes compilados
Hubo otros resultados interesantes. Los lenguajes compilados «tienden a ser» los más eficientes energéticamente y los que más rápido funcionan, y su documento puede incluso cuantificar esa diferencia con un número. «En promedio, los lenguajes compilados consumieron 120J para ejecutar las soluciones, mientras que para una máquina virtual y los lenguajes interpretados este valor fue de 576J y 2365J, respectivamente.»
Los investigadores también aplicaron la misma precisión al comparar los tiempos de ejecución, concluyendo que en promedio, «los lenguajes compilados tardaron 5103ms, los lenguajes de máquina virtual tardaron 20623ms, y los lenguajes interpretados tardaron 87614ms.»
De los cinco primeros lenguajes en ambas categorías, cuatro de ellos eran compilados. (¿La excepción? Java.)
Energía consumida | Tiempo detiempo | |
C | 57J | 2019 ms |
Rust | 59J | 2103 ms |
C++ | 77J | 3155 ms |
Ada | 98J | 3740 ms |
Java | 114J | 3821 ms |
Los cinco lenguajes más lentos eran todos interpretados: Lua, Python, Perl, Ruby y Typescript. Y los cinco lenguajes que más energía consumían también eran interpretados: Perl, Python, Ruby, JRuby y Lua.
Pero al mismo tiempo, cuando se manipulan cadenas con expresiones regulares, tres de los cinco lenguajes más eficientes energéticamente resultan ser lenguajes interpretados (TypeScript, JavaScript y PHP), «aunque tienden a ser poco eficientes energéticamente en otros escenarios».
Los lenguajes compilados también ocuparon los cinco primeros puestos en cuanto a la menor cantidad de espacio de memoria utilizado.
Lenguaje | Espacio de memoria necesario |
Pascal | 66Mb |
Go | 69Mb |
C | 77Mb |
Fortran | 82Mb |
C++ | 88Mb |
«De media, los lenguajes compilados necesitaron 125Mb, los de máquina virtual 285Mb y los interpretados 426Mb», informan los investigadores. Por su parte, los lenguajes interpretados ocuparon cuatro de los cinco últimos puestos, es decir, fueron los que más espacio de memoria consumieron: JRuby, Dart, Lua y Perl. (Aunque Erlang no es un lenguaje interpretado, también aparecería entre los cinco últimos, entre Dart y Lua).
«Si se clasifican por su paradigma de programación, los lenguajes imperativos necesitaron 116Mb, los orientados a objetos 249Mb, los funcionales 251Mb y, por último, los scripts necesitaron 421Mb». Sus programas de referencia también utilizaron mucha menos energía en promedio -y se ejecutaron mucho más rápido- que los programas de referencia para los paradigmas orientados a objetos, funcionales y de secuencias de comandos.
Energía consumida | Tiempo de ejecución | |
Imperativo | 125J | 5585ms |
Objeto-Orientado | 879J | 32965ms |
Funcional | 1367J | 42740ms |
Scripting | 2320J | 88322 ms |
Pero hay muchos factores a considerar. «Está claro que los diferentes paradigmas de programación e incluso los lenguajes dentro del mismo paradigma tienen un impacto completamente diferente en el consumo de energía, el tiempo y la memoria», escriben los investigadores. Pero cuál de ellos es el más importante dependerá de tu escenario. (Las tareas en segundo plano, por ejemplo, no siempre necesitan el tiempo de ejecución más rápido..)
Y algunas aplicaciones requieren la consideración de dos factores, por ejemplo, el uso de energía y el tiempo de ejecución. En ese caso, «C es la mejor solución, ya que es dominante en ambos objetivos individuales», escriben los investigadores. Si se trata de ahorrar tiempo utilizando menos memoria, C, Pascal y Go «son equivalentes», y lo mismo ocurre si se observan las tres variables (tiempo, uso de energía y uso de memoria). Pero si sólo estás tratando de ahorrar energía mientras usas menos memoria, tus mejores opciones son C o Pascal.
Al final del documento, los investigadores añaden que para un estudio posterior, les gustaría examinar si el uso total de la memoria en el tiempo se correlaciona mejor con la energía consumida.
Comparten sus datos en línea, sugiriendo que facilita a futuros investigadores la comparación, por ejemplo, de lenguajes .NET o JVM. Para los desarrolladores que trabajan con aplicaciones móviles, sistemas de Internet de las Cosas u otras aplicaciones que utilizan fuentes de alimentación limitadas, el consumo de energía es una preocupación importante.
Pero al final, el estudio también puede dejar a los programadores con lo que más odian: la ambigüedad. Los investigadores informan de que si se busca un único y mejor lenguaje de programación, «esta pregunta no tiene una respuesta concreta y definitiva.
«Aunque el lenguaje más eficiente energéticamente en cada punto de referencia es casi siempre el más rápido, el hecho es que no hay ningún lenguaje que sea sistemáticamente mejor que los demás», concluyen los investigadores. «La situación en la que se va a utilizar un lenguaje es un aspecto fundamental para determinar si ese lenguaje es la opción más eficiente desde el punto de vista energético.»