Mely programozási nyelvek használják a legkevesebb áramot?
Az energiafelhasználási adatok elárulnak valamit a programozási nyelveink minőségéről?
Tavaly egy hat portugál kutatócsoport három különböző egyetemről úgy döntött, hogy megvizsgálja ezt a kérdést, és végül kiadta “Energy Efficiency Across Programming Languages” című tanulmányát. Lefuttatták 10, 27 különböző nyelven írt programozási probléma megoldását, miközben gondosan figyelték, hogy mindegyik mennyi áramot használt – valamint a sebességet és a memóriahasználatot.
Konkrétan 10 problémát használtak a Computer Language Benchmarks Game-ből, egy ingyenes szoftverprojektből a teljesítmény összehasonlítására, amely egyszerű algoritmikus problémák szabványos készletét, valamint egy keretrendszert tartalmaz a tesztek futtatásához. (Korábban “The Great Computer Language Shootout” néven volt ismert.) “Ez lehetővé tette számunkra, hogy összehasonlítható, reprezentatív és kiterjedt programkészletet kapjunk… a fordítási/futtatási lehetőségekkel és a fordítóverziókkal együtt.”
Ez azért volt fontos, hogy többféle benchmark-tesztet futtassanak, mert végül az eredményeik attól függően változtak, hogy melyik tesztet végezték. Összességében például a C nyelv bizonyult a leggyorsabbnak és egyben a leg energiatakarékosabbnak is. Abban a benchmark-tesztben azonban, amely egy DNS-adatbázis egy adott genetikai szekvencia keresését tartalmazta, a Rust volt a leg energiatakarékosabb – míg a C a harmadik helyen végzett.
Még ugyanezen a teszten belül is attól függ, hogy mi a “legjobb” nyelv, hogy mi a kritérium. Ebben a tesztben a C szintén csak a második leggyorsabb nyelvnek bizonyult (ismét a Rust mögött). A Rust azonban kilenc helyet esett vissza, ha az eredményeket a memóriahasználat alapján rendeztük. És bár a Fortran volt a második leg energiatakarékosabb nyelv ebben a tesztben, szintén hat helyet esett vissza, ha az eredményeket inkább a végrehajtási idő alapján rendezték.
A gyorsabb nyelv nem mindig a leg energiatakarékosabb.
A kutatók megjegyzik, hogy “szigorúan követték” a CLBG projekt irányelveit a fordítóverziókról és a legjobb optimalizálási zászlókról. Az energiafogyasztást az Intel egyik eszközével – a Running Average Power Limit eszközzel – úgy mérték, hogy minden programot nem csak egyszer, hanem tízszer hajtottak végre, “hogy csökkentsék a hidegindítások és a gyorsítótárhatások hatását, valamint hogy elemezni tudják a mérések konzisztenciáját és elkerüljék a kiugró értékeket”. (Emiatt arról számolnak be, hogy “a mért eredmények meglehetősen konzisztensek”.) A további konzisztencia érdekében az összes tesztet egy asztali számítógépen végezték, amelyen Linux Ubuntu Server 16.10 (kernel 4.8.0-22-generic verzió) futott, 16 GB RAM-mal és 3,20 GHz-es Haswell Intel Core i5-4460 CPU-val.
A tanulmányukban a kutatók néhány érdekes eredményt neveznek meg:
“A Lisp átlagosan 2.27x több energiát (131,34J), mint a C, miközben 2,44x több időt vesz igénybe a végrehajtás (4926,99ms), és 1,92x több memóriát (126,64Mb) igényel a Pascalhoz képest.”
A fordított nyelvek és az értelmezett nyelvek eredményeit is összehasonlították (a virtuális gépeken futó nyelvek külön kategóriát kaptak). A tanulmány külön összehasonlítást tartalmaz a különböző programozási paradigmákról is – beleértve a funkcionális és imperatív programozást, valamint az objektumorientált programozást és a szkriptelést is.
A gyorsabb zöldebb?
A tanulmány alaposan megvizsgálta azt az általános feltételezést, hogy egy gyorsabb program mindig kevesebb energiát használ, rámutatva, hogy ez nem olyan egyszerű, mint a fizika törvénye, amely szerint E(nergy) = T(ime) x P(ower). Ez részben azért van így, mert az energiafelhasználás nem egyenletes ütemben történik – jegyzik meg a kutatók, akik szerint ez hatással lehet más kutatók munkájára, akik azt vizsgálják, hogy egy program futási ideje befolyásolja-e az energiafogyasztást. (“Az ezzel kapcsolatos következtetések néha eltérnek egymástól…”) Az egyik benchmark-tesztjükben egy Chapel program végrehajtása 55 százalékkal kevesebb időt vett igénybe, mint egy egyenértékű, Pascal nyelven írt programé – és mégis ez a Pascal program 10 százalékkal kevesebb energiát használt fel.
Míg tehát még mindig elterjedt az a hiedelem, hogy az energiafogyasztás csökken, ha a programok gyorsabban futnak, a kutatók egyértelműen kijelentik, hogy “a gyorsabb nyelv nem mindig a leg energiatakarékosabb.”
Nehéz lehet megválaszolni ezt a kérdést, mivel az energiafogyasztást számos tényező befolyásolja (többek között a fordító minősége és az, hogy milyen könyvtárakat használunk). De végül a kutatók még az energiafogyasztást is képesek voltak lebontani aszerint, hogy azt a CPU vagy a DRAM fogyasztja – arra a következtetésre jutottak, hogy az energiafogyasztás nagy részét (körülbelül 88 százalékát) átlagosan a CPU fogyasztotta, függetlenül attól, hogy a referenciaprogramot fordították, értelmezték vagy virtuális gépen futtatták-e.
Érdekes, hogy az értelmezett nyelveknél valamivel nagyobb eltérés mutatkozott, a CPU néha 92 százalékot is fogyasztott.90 százalékát, vagy csak 81,57 százalékát.
A kutatók az eredményeik tanulmányozása után arra a következtetésre is jutottak, hogy a DRAM csúcshasználata és az energiafogyasztás közötti kapcsolat “szinte nem létezik.”
A kutatás újabb betekintést nyújt az örök kérdésbe: zöldebb-e a gyorsabb? Igen, igaz, hogy “az első öt leginkább energiahatékony nyelv megtartja rangsorát, ha a végrehajtási idő szerint rendezzük őket, és mind az energia-, mind az időértékek tekintetében nagyon kis különbségekkel.”
Sőt, 10 benchmark-probléma közül kilenc esetében a legjobb eredményt (mind a sebesség, mind az energiahatékonyság tekintetében) az összességében leggyorsabb és leginkább energiahatékony nyelvek közül az első három közül az egyik kapta – ami nem lepte meg a kutatókat. “Köztudott, hogy ez a három legjobb nyelv (C, C++ és Rust) köztudottan erősen optimalizált és hatékony a végrehajtási teljesítmény szempontjából, amint azt az adataink is mutatják.”
A másik 24 nyelv futási idő szerinti rangsorolásakor azonban nem ugyanazt a sorrendet látjuk, mint az energiahatékonyság szerinti rangsoroláskor. “Csak négy nyelv tartja meg ugyanazt az energia- és időbeli rangsort (OCaml, Haskel, Racket és Python), míg a többi teljesen megkeveredik.”
És még az egyes benchmark teszteken is vannak olyan esetek, amikor a gyors teljesítményű nyelvek nem a leg energiatakarékosabbak.
A fordított nyelvek előnyei
Más érdekes eredmények is születtek. A lefordított nyelvek “általában” a leg energiatakarékosabbak és a leggyorsabban futóak – és tanulmányuk ezt a különbséget még számmal is tudja számszerűsíteni. “Átlagosan a fordított nyelvek 120J-t fogyasztottak a megoldások végrehajtásához, míg a virtuális gép és az értelmezett nyelvek esetében ez az érték 576J, illetve 2365J volt.”
A kutatók ugyanezt a pontosságot alkalmazták a végrehajtási idők összehasonlításakor is, és arra a következtetésre jutottak, hogy átlagosan “a fordított nyelveknek 5103ms, a virtuális gépes nyelveknek 20623ms, az értelmezett nyelveknek pedig 87614ms kellett.”
Az első öt nyelv közül mindkét kategóriában négy fordított volt. (Kivétel a Java.)
Energiafogyasztás | Futtatás…idő | |
C | 57J | 2019 ms |
Rust | 59J | 2103 ms |
C++ | 77J | 3155 ms |
Ada | 98J | 3740 ms |
Java | 114J | 3821 ms |
Az öt leglassabb nyelv mind interpretált volt: Lua, Python, Perl, Ruby és Typescript. És az öt legtöbb energiát fogyasztó nyelv is értelmezett volt: Perl, Python, Ruby, JRuby és Lua.
De ugyanakkor a karakterláncok szabályos kifejezéssel való manipulálásakor az öt leg energiatakarékosabb nyelv közül háromról kiderült, hogy értelmezett nyelvek (TypeScript, JavaScript és PHP), “bár más forgatókönyvekben általában nem túl energiatakarékosak.”
A legkevesebb memóriahasználat tekintetében is a fordított nyelvek foglalták el az első öt helyet.
Nyelv | Memóriaterületigény |
Pascal | 66Mb |
Go | 69Mb |
C | 77Mb |
Fortran | 82Mb |
C++ | 88Mb |
“Átlagosan, a lefordított nyelvek 125 Mb-ot, a virtuális gépi nyelvek 285 Mb-ot, az értelmezettek pedig 426 Mb-ot igényeltek” – írják a kutatók. Eközben az öt legalsó helyből négyet az értelmezett nyelvek foglaltak el, ami azt jelenti, hogy ezek fogyasztották a legtöbb memóriaterületet: JRuby, Dart, Lua és Perl. (Bár az Erlang nem értelmezett nyelv, szintén az alsó ötben szerepelne, a Dart és a Lua között).
“Ha a programozási paradigma szerint rendezzük, az imperatív nyelvek 116 Mb-ot, az objektumorientáltak 249 Mb-ot, a funkcionálisak 251 Mb-ot, végül a szkriptnyelvek 421 Mb-ot igényeltek.”
A különböző paradigmák összehasonlításakor gyakran az imperatív programozás végzett az élen. A benchmark programjai is átlagosan sokkal kevesebb energiát használtak – és sokkal gyorsabban futottak -, mint az objektumorientált, a funkcionális és a szkriptelési paradigmák benchmark programjai.
Fogyasztott energia | Futási idő | |
Imperatív | 125J | 5585ms |
Object-Orientált | 879J | 32965ms |
Funkcionális | 1367J | 42740ms |
Szerkesztés | 2320J | 88322 ms |
De sok tényezőt kell figyelembe venni. “Világos, hogy a különböző programozási paradigmák, sőt még az ugyanazon paradigmán belüli nyelvek is teljesen eltérő hatással vannak az energiafogyasztásra, az időre és a memóriára” – írják a kutatók. Mégis, hogy ezek közül melyik a legfontosabb, az a forgatókönyvtől függ. (A háttérfeladatoknak például nem mindig a leggyorsabb futási időre van szükségük..)
És vannak olyan alkalmazások, amelyeknél két tényezőt – például az energiafelhasználást és a végrehajtási időt – is figyelembe kell venni. Ebben az esetben “a C a legjobb megoldás, mivel mindkét egyes cél tekintetében domináns” – írják a kutatók. Ha időt akarunk megtakarítani, miközben kevesebb memóriát használunk, a C, a Pascal és a Go “egyenértékű” – és ugyanez igaz, ha mindhárom változót (idő, energiafelhasználás és memóriahasználat) figyeljük. De ha csak energiát próbálunk megtakarítani, miközben kevesebb memóriát használunk, akkor a legjobb választás a C vagy a Pascal.”
A tanulmány végén a kutatók hozzáteszik, hogy a további vizsgálatok során szeretnék megvizsgálni, hogy az időbeli teljes memóriahasználat jobban korrelál-e a felhasznált energiával.
Az adataikat online megosztják, azt sugallva, hogy ez megkönnyíti a jövőbeli kutatók számára például a .NET-nyelvek vagy a JVM-nyelvek összehasonlítását. A mobilalkalmazásokkal, Internet-of-Things rendszerekkel vagy más, korlátozott energiaellátásból merítő alkalmazásokkal dolgozó fejlesztők számára az energiafogyasztás komoly aggodalomra ad okot.
De végül a tanulmány a programozóknak is azt hagyhatja, amit a legjobban utálnak: a kétértelműséget. A kutatók arról számolnak be, hogy ha egyetlen legjobb programozási nyelvet keresünk, “erre a kérdésre nincs konkrét és végleges válasz.”
“Bár az egyes benchmarkokban szinte mindig a leggyorsabb az energiatakarékosabb nyelv, tény, hogy nincs olyan nyelv, amely következetesen jobb lenne a többinél” – állapítják meg a kutatók. “Az a helyzet, amelyben egy nyelvet használni fognak, alapvető szempont annak eldöntéséhez, hogy az adott nyelv a leg energiatakarékosabb megoldás-e.”