Software verbraucht Energie – auf Servern, bei Builds, im Deployment. Jede gesparte Millijoule zählt – für die Umwelt und die Serverrechnung.
Bisher fehlten uns jedoch die Werkzeuge, um den Energieverbrauch auf Code-Ebene zu messen. Die gängigen Benchmarks messen Speed, aber nicht Impact.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.
Oaklean ist unser Open-Source-Tool, das genau das ermöglicht. Wir können den Energieverbrauch bis auf jede einzelne Zeile Code messen. Das gibt uns erstmals echte Daten, wo unsere Software tatsächlich Energie verbraucht, nicht nur Theorien.
Wie verhält sich Bun in diesem Vergleich?
Dieser Frage wollten wir nachgehen und haben in einem echten Projekt nachgemessen.
Um präzise Daten zu erhalten, haben wir das Tool powermetrics auf macOS verwendet. Es erlaubt uns, den Energieverbrauch auf Prozessebene zu tracken. Der Befehl zum Starten der Messung sieht wie folgt aus:
sudo powermetrics --show-process-energy --sample-rate 500 --buffer-size 0 -f plist -o ~/tmp/energy_measurements_node.plist
Die Messungen basieren nicht auf theoretischen Benchmarks, sondern auf einem realen Kundenprojekt. Wir haben die Applikation einmal mit Node.js und einmal mit Bun gestartet, sie unter Volllast gesetzt und dabei einen reproduzierbaren Datensatz verwendet. Gesteuert wurde die Messung über ein einfaches Bash-Skript, das den Prozess für 30 Sekunden unter diesen Bedingungen laufen lässt und die Daten in der Plist-Datei speichert.
Der entscheidende Teil ist jedoch die Auswertung. Da powermetrics die Daten standardmäßig in einer Plist-Datei speichert, müssen wir diese gezielt interpretieren.
Um die rohen Daten von powermetrics in verwertbare Energiewerte umzurechnen, nutzen wir die Bibliothek @oaklean/profiler-core. Unser Skript liest die Plist-Datei ein und wertet sie selektiv aus:
import fs from 'fs'
import plist from 'plist'
import {
PowerMetricsData,
IPowerMetricsOutputFormat,
MetricsDataCollection,
MetricsDataCollectionType,
NanoSeconds_BigInt
} from '@oaklean/profiler-core'
// Laden der Plist-Daten
const inputPlist = process.argv[3] || 'power_metrics.plist'
const content = fs.readFileSync(inputPlist).toString()
const contents = content.split('\x00')
const pid = process.argv[2] ? parseInt(process.argv[2]) : 0
const collection = new MetricsDataCollection(
pid,
MetricsDataCollectionType.PowerMetricsPerProcess,
data,
{
startTime: BigInt(0),
stopTime: BigInt(0)
}
)
let totalEnergy = 0
for (const item of collection.items) {
if (item.processIsPresent(pid)) {
// Hier passiert die Magie: Anteil des Prozesses an der CPU-Energie
const energy = item.energyPortionOfProcess(pid) * item.cpuEnergy()
totalEnergy += energy
}
}
console.log(totalEnergy)
Das Skript berechnet den exakten Anteil, den unser Prozess am gesamten CPU-Energieverbrauch hat. Durch die Integration von @oaklean/profiler-core wird die komplexe Interpretation der powermetrics-Daten abstrahiert und wir erhalten einen vergleichbaren Energiewert.
Die Zahlen sprechen eine deutliche Sprache. In unseren Tests (30 Sekunden Laufzeit unter Last) ergaben sich folgende Werte:
| Runtime | Energieverbrauch |
|---|---|
| Bun | 1930 mJ |
| Node.js (v20) | 3160 mJ |
| Node.js (v25) | 4726 mJ |
Bun verbraucht in diesem Projekt fast 40% weniger Energie als Node.js v20 und sogar weniger als die Hälfte von Node.js v25.
Die Wahl der Runtime hat einen direkten Einfluss auf den ökologischen Fußabdruck unserer Anwendungen. Bun ist nicht nur schnell und bietet eine hervorragende Developer Experience, sondern ist auch in puncto Energieeffizienz ein echter Gamechanger.
Und jetzt stellt sich die spannende Frage: Wie könnte eine Energiemessung in der Bun Engine selbst aussehen, so wie wir es in der Node.js Engine umgesetzt haben? Aber selbst ohne Bun-Engine-Messung lassen sich mit Oaklean heute bereits die Energie-Bottle-Necks in Bun-Projekten finden.
Wenn man Wert auf Green Coding legt und die eigene Server-Rechnung entlasten möchte, ist der Wechsel zu Bun ein logischer Schritt.