Hvilke programmeringssprog bruger mindst elektricitet?
Kan data om energiforbrug fortælle os noget om kvaliteten af vores programmeringssprog?
Forrige år besluttede et hold på seks forskere i Portugal fra tre forskellige universiteter at undersøge dette spørgsmål og offentliggjorde i sidste ende et dokument med titlen “Energy Efficiency Across Programming Languages”. De kørte løsningerne på 10 programmeringsproblemer skrevet i 27 forskellige sprog, mens de nøje overvågede, hvor meget elektricitet hvert enkelt sprog brugte – samt dets hastighed og hukommelsesforbrug.
Specifikt brugte de 10 problemer fra Computer Language Benchmarks Game, et gratis softwareprojekt til sammenligning af ydeevne, som omfatter et standardsæt af enkle algoritmiske problemer samt en ramme til at køre tests. (Det var tidligere kendt som “The Great Computer Language Shootout.”) “Dette gjorde det muligt for os at få et sammenligneligt, repræsentativt og omfattende sæt af programmer … sammen med kompilerings-/udførelsesmulighederne og compilerversionerne.”
Det var vigtigt at køre en række forskellige benchmark-tests, fordi deres resultater i sidste ende varierede afhængigt af, hvilken test der blev udført. F.eks. viste det sig overordnet set, at C-sproget var det hurtigste og også det mest energieffektive. Men i benchmark-testen, som gik ud på at scanne en DNA-database for en bestemt genetisk sekvens, var Rust det mest energieffektive – mens C kom ind på tredjepladsen.
Men selv inden for den samme test afhænger det “bedste” sprog af, hvad dit kriterium er. I denne test viste C sig også kun at være det næsthurtigste sprog (igen med en placering bag Rust). Men Rust faldt hele ni pladser, hvis resultaterne blev sorteret efter hukommelsesforbrug. Og mens Fortran var det næstmest energieffektive sprog i denne test, faldt det også hele seks pladser, når resultaterne i stedet blev sorteret efter udførelsestid.
Et hurtigere sprog er ikke altid det mest energieffektive.
Forskerne bemærker, at de “nøje fulgte” CLBG-projektets retningslinjer om compilerversioner og de bedste optimeringsflag. Strømforbruget blev målt ved hjælp af et værktøj fra Intel – Running Average Power Limit-værktøjet – hvor hvert program blev udført ikke bare én gang, men 10 gange, “for at reducere virkningen af koldstarter og cache-effekter og for at kunne analysere målingernes konsistens og undgå outliers”. (Af denne grund rapporterer de, at “de målte resultater er ret konsistente.”) For ekstra konsistens skyld blev alle testene udført på en stationær computer med Linux Ubuntu Server 16.10 (kerneversion 4.8.0-22-generic), med 16 GB RAM og en 3,20 GHz Haswell Intel Core i5-4460 CPU.
I deres artikel fremhæver forskerne nogle interessante resultater.
“Lisp bruger i gennemsnit 2.27x mere energi (131,34 J) end C, mens det tager 2,44x mere tid at udføre (4926,99 ms), og der er brug for 1,92x mere hukommelse (126,64 Mb) sammenlignet med Pascal.”
De sammenlignede også resultaterne fra kompilerede sprog versus fortolkede sprog (med en separat kategori for sprog, der kører på virtuelle maskiner). Og dokumentet indeholder også en separat sammenligning af de forskellige programmeringsparadigmer – herunder både funktionel og imperativ programmering samt objektorienteret programmering og scripting.
Er hurtigere grønnere?
Dokumentet tog et grundigt kig på den almindelige antagelse, at et hurtigere program altid vil bruge mindre energi, og påpegede, at det ikke er så simpelt som den fysiske lov, der siger E(nergy) = T(ime) x P(ower). Dette skyldes til dels, at strømmen ikke forbruges med en ensartet hastighed, bemærker forskerne og antyder, at det kan have indflydelse på andre forskeres arbejde med at undersøge, om et programs løbetid påvirker dets energiforbrug. (“Konklusionerne vedrørende dette spørgsmål divergerer nogle gange…”) I en af deres benchmark-tests tog et Chapel-program 55 procent mindre tid at udføre end et tilsvarende program skrevet i Pascal – og alligevel brugte det Pascal-program 10 procent mindre energi.
Så selv om der stadig er en udbredt tro på, at energiforbruget falder, når programmerne kører hurtigere, fastslår forskerne utvetydigt, at “et hurtigere sprog ikke altid er det mest energieffektive.”
Det kan være et svært spørgsmål at besvare, da energiforbruget påvirkes af mange faktorer (herunder kvaliteten af compileren, og hvilke biblioteker der anvendes). Men i sidste ende var forskerne endda i stand til at opdele energiforbruget efter, om det blev forbrugt af CPU’en eller DRAM – og konkluderede, at størstedelen af strømmen (ca. 88 procent) i gennemsnit blev forbrugt af CPU’en, uanset om benchmarkprogrammet var kompileret, fortolket eller kørt på en virtuel maskine.
Interessant nok viste fortolkede sprog en lidt større variation, hvor CPU’en nogle gange brugte så meget som 92.90 procent af strømmen eller så lidt som 81,57 procent.
Efter at have studeret deres resultater konkluderede forskerne også, at forholdet mellem spidsforbruget af DRAM og energiforbruget “er næsten ikke-eksisterende.”
Forskningen giver yderligere indsigt i det evige spørgsmål: Er hurtigere grønnere? Ja, det er rigtigt, at “de fem mest energieffektive sprog bevarer deres rang, når de sorteres efter udførelsestid og med meget små forskelle i både energi- og tidsværdier.”
Faktisk set kom topscoren (for både hastighed og energieffektivitet) for ni ud af ti benchmarkproblemer fra et af de tre hurtigste og mest energieffektive sprog i alt – hvilket ikke overraskede forskerne. “Det er almindelig kendt, at disse tre bedste sprog (C, C++ og Rust) er kendt for at være stærkt optimerede og effektive med hensyn til eksekveringspræstationer, hvilket vores data også viser.”
Men man ser ikke den samme rækkefølge, når man rangordner de andre 24 sprog efter deres køretid, som man gør, når man rangordner dem efter energieffektivitet. “Kun fire sprog bevarer den samme energi- og tidsrækkefølge (OCaml, Haskel, Racket og Python), mens resten er fuldstændig blandet.”
Og selv i de enkelte benchmark-tests er der tilfælde, hvor de hurtigt præsterende sprog ikke er de mest energieffektive.
Fordelene ved kompilerede sprog
Der var andre interessante resultater. Kompilerede sprog “har en tendens til at være” de mest energieffektive og hurtigst kørende – og deres artikel kan endda kvantificere denne forskel med et tal. “I gennemsnit brugte kompilerede sprog 120 J til at udføre løsningerne, mens denne værdi for en virtuel maskine og fortolkede sprog var henholdsvis 576 J og 2365 J.”
Forskerne anvendte også samme præcision ved sammenligning af udførelsestider og konkluderede, at “kompilerede sprog i gennemsnit tog 5103 ms, virtuelle maskinesprog tog 20623 ms, og fortolkede sprog tog 87614 ms.”
Af de fem bedste sprog i begge kategorier var fire af dem kompilerede. (Undtagelsen? Java.)
Energiforbrug | Run-tid | |
C | 57J | 2019 ms |
Rust | 59J | 2103 ms |
C++ | 77J | 3155 ms |
C++ | 77J | 3155 ms |
Ada | 98J | 3740 ms |
Java | 114J | 3821 ms |
De fem langsomste sprog var alle fortolkede: Lua, Python, Perl, Ruby og Typescript. Og de fem sprog, der brugte mest energi, var også fortolkede: Perl, Python, Ruby, JRuby og Lua.
Men samtidig viser det sig, at når der manipuleres strenge med regulære udtryk, er tre af de fem mest energieffektive sprog fortolkede sprog (TypeScript, JavaScript og PHP), “selv om de har tendens til ikke at være særlig energieffektive i andre scenarier.”
Samlede sprog indtog også de fem øverste pladser for mindst forbrug af hukommelsesplads.
Sprog | Memory space needed |
Pascal | 66Mb |
Go | 69Mb |
C | 77Mb |
Fortran | 82Mb |
C++ | 88Mb |
“I gennemsnit, de kompilerede sprog 125 Mb, de virtuelle maskinesprog 285 Mb og de fortolkede 426 Mb,” rapporterer forskerne. I mellemtiden hævdede fortolkede sprog fire af de fem nederste pladser, hvilket betyder, at de brugte mest hukommelsesplads: JRuby, Dart, Lua og Perl. (Selv om Erlang ikke er et fortolket sprog, ville det også optræde i de fem nederste, mellem Dart og Lua).
“Hvis man sorterer efter deres programmeringsparadigme, havde de imperative sprog brug for 116 Mb, de objektorienterede 249 Mb, de funktionelle 251 Mb og endelig havde scripting brug for 421 Mb.”
Faktisk set, når man sammenligner de forskellige paradigmer, kom imperativ programmering ofte øverst på listen. Dens benchmarkprogrammer brugte også i gennemsnit langt mindre energi – og kørte meget hurtigere – end benchmarkprogrammerne for de objektorienterede, funktionelle og scripting-paradigmer.
Energiforbrug | Kør-tid | |
Imperativ | 125J | 5585ms |
Objekt-Oriented | 879J | 32965ms |
Functional | 1367J | 42740ms |
Scripting | 2320J | 88322 ms |
Men der er mange faktorer, der skal tages i betragtning. “Det er klart, at forskellige programmeringsparadigmer og endda sprog inden for det samme paradigme har en helt forskellig indvirkning på energiforbrug, tid og hukommelse,” skriver forskerne. Alligevel vil det afhænge af dit scenarie, hvilken af disse der er vigtigst. (Baggrundsopgaver har f.eks. ikke altid brug for den hurtigste køretid…)
Og nogle applikationer kræver, at man tager hensyn til to faktorer – f.eks. energiforbrug og eksekveringstid. I det tilfælde er “C den bedste løsning, da den er dominerende inden for begge enkeltmål,” skriver forskerne. Hvis man forsøger at spare tid og samtidig bruge mindre hukommelse, er C, Pascal og Go “ækvivalente” – og det samme gælder, hvis man holder øje med alle tre variabler (tid, energiforbrug og hukommelsesforbrug). Men hvis du blot forsøger at spare energi, mens du bruger mindre hukommelse, er dine bedste valg C eller Pascal.
I slutningen af dokumentet tilføjer forskerne, at de i forbindelse med yderligere undersøgelser gerne vil undersøge, om det samlede hukommelsesforbrug over tid korrelerer bedre med det forbrugte energiforbrug.
De deler deres data online og antyder, at det gør det lettere for fremtidige forskere at sammenligne f.eks. .NET-sprog eller JVM-sprog. For udviklere, der arbejder med mobilapplikationer, Internet-of-Things-systemer eller andre apps, der trækker på begrænsede strømforsyninger, er strømforbruget en stor bekymring.
Men i sidste ende kan undersøgelsen også efterlade programmørerne med det, de hader mest: tvetydighed. Forskerne rapporterer, at hvis du leder efter et enkelt bedste programmeringssprog, “har dette spørgsmål ikke et konkret og ultimativt svar.”
“Selv om det mest energieffektive sprog i hver benchmark næsten altid er det hurtigste, er det en kendsgerning, at der ikke er noget sprog, der konsekvent er bedre end de andre,” konkluderer forskerne. “Den situation, som et sprog skal bruges i, er et centralt aspekt for at afgøre, om det pågældende sprog er den mest energieffektive løsning.”