Architektura i Eksperymenty
Ostatnia aktualizacja: 2026-05-28
Architektura systemu
Opis ogólny
System pomiarowy do rygorystycznej analizy energetycznej środowisk uruchomieniowych JavaScript (Node.js, Deno, Bun) w workloadach serverless. Główny wkład techniczny: standaryzowana metodologia uwzględniająca JIT warm-up i GC pauses (luka w literaturze), pierwsza porównawcza analiza energetyczna Node.js/Deno/Bun, oraz wielokryterialny model decyzyjny energia–latencja–koszt.
Komponenty główne
| Komponent | Opis | Technologia |
|---|---|---|
| M1 – Workload Suite | 6 kategorii workloadów (CPU, I/O, SSR, cold start, memory, mixed) | Node.js/Deno/Bun skrypty |
| M2 – Energy Measurement | Process-level energy attribution via RAPL + PowerJoular | Intel RAPL, PowerJoular |
| M3 – JIT Warm-up Protocol | Automatyczne odrzucanie N iteracji warm-up; Ljung-Box stationarity test | Python orchestrator |
| M4 – GC Profiler | Detekcja i filtrowanie GC pause spikes z energy trace | V8/JSC GC hooks |
| M5 – Statistical Analyzer | Median/IQR, Mann-Whitney U, Kruskal-Wallis, effect size | R / Python scipy |
| M6 – Decision Model | TOPSIS multi-criteria (energia × latencja × koszt) | Python topsis |
Przepływ danych
flowchart TD WD([Workload definition]) --> M1[M1 Workload Suite\n6 categories × 3 runtimes] M1 --> BM[Bare-metal server\nUbuntu 24.04, Intel] BM --> M2[M2 RAPL + PowerJoular\nprocess-level energy] M2 --> M3[M3 JIT Warm-up Protocol\nodrzuć pierwsze N iteracji] M3 --> M4[M4 GC Profiler\nwykryj i filtruj GC spikes] M4 --> RAW([Raw energy + time series\n30 pomiarów per runtime × workload]) RAW --> M5[M5 Statistical Analyzer\nmedian, IQR, Mann-Whitney U] M5 --> STATS([Wyniki statystyczne\np-values, effect sizes]) STATS --> M6[M6 TOPSIS Decision Model\nenergia × latencja × koszt] M6 --> RANK([Ranking: runtime × workload × platform])
Stack technologiczny
| Warstwa | Technologia | Uzasadnienie |
|---|---|---|
| Runtimes | Node.js 24 LTS, Deno 2.x, Bun 1.x | obiekty badania |
| Pomiar energii | Intel RAPL (perf stat), PowerJoular; Kepler (K8s) | process-level attribution; K8s-aware alternative |
| Środowisko | bare-metal Intel server, Ubuntu 24.04 | eliminacja hypervisor noise |
| Orchestracja | Python 3.11 + subprocess | automatyzacja 30 powtórzeń |
| Statystyki | scipy.stats, R (lawstat) | Mann-Whitney U, Ljung-Box |
| Model decyzyjny | topsis-python | TOPSIS MCDM |
| Dane | własne pomiary benchmark | brak zewnętrznych datasets |
Eksperymenty
JE-EXP-1: Energia Node.js vs Deno vs Bun — 6 Kategorii Workloadów
Status: in_progress (uruchomiony 2026-05-28, serwer: je-benchmark 138.201.19.49)
Priorytet: high
Powiązany pomysł: JE-1
Dodano: 2026-05-27
Hipoteza: Bun zużywa istotnie mniej energii niż Node.js dla CPU-bound workloadów (JavaScriptCore < V8 dla synchronicznej egzekucji JS), podczas gdy dla async I/O Deno jest energetycznie zbliżony lub lepszy niż Node.js (Tokio runtime). Nie istnieje runtime “zawsze najlepszy” dla wszystkich kategorii workloadów.
Dane:
- Dataset: własne pomiary (brak zewnętrznych)
- Podział: 30 powtórzeń per (runtime × workload × kategoria); 5 warm-up odrzucanych
- Preprocessing: odfiltrowanie outlierów GC (IQR × 1.5), normalizacja do J/request
Metoda:
- Przygotowanie workload suite: sortowanie (CPU), SHA256 hashing (CPU), JSON parse/stringify (CPU), file I/O (I/O), HTTP fetch (I/O), SQLite queries (I/O), SSR Handlebars (mixed), cold start to first response, large array ops (memory)
- Kontrola środowiska: bare-metal Intel server, CPU governor=performance, izolacja na dedykowanym core
- Pomiar: PowerJoular process-level (RAPL PACKAGE + DRAM) + wall clock time + RSS memory
- Protokół:
perf stat -e power/energy-pkg/zsynchronizowany z PowerJoular; warm-up 5 iteracji odrzucanych - Stacjonarność: Ljung-Box test na energy time series (p>0.05 = stacjonarny)
- Statystyki: median ± IQR, Mann-Whitney U dla każdej pary (Bun vs Node.js, Deno vs Node.js)
Modele / Baseline:
| Model | Opis |
|---|---|
| Node.js 24 LTS | reference baseline |
| Deno 2.x | Rust/Tokio async |
| Bun 1.x | JavaScriptCore, szybki startup |
Metryki:
- Główna: energia [J/request] i czas [ms/request] per (runtime × workload)
- Dodatkowe: RSS memory [MB], cold start energia [J], effect size (Cohen’s d)
- Test statystyczny: Mann-Whitney U (α=0.05), Kruskal-Wallis dla 3 grup
Wyniki: (do wypełnienia po wykonaniu)
| Workload | Node.js [J] | Deno [J] | Bun [J] | p-value (Bun vs Node) |
|---|
Wnioski: (do wypełnienia po wykonaniu)
JE-EXP-2: Standaryzacja Metodologii Pomiaru Energii JS Runtimeów
Status: in_progress (uruchomiony 2026-05-28, poprzedza EXP-1)
Priorytet: high
Powiązany pomysł: JE-3
Dodano: 2026-05-27
Hipoteza: JIT warm-up w Node.js/Deno (V8) wymaga co najmniej 10-15 iteracji przed stabilizacją zużycia energii (Ljung-Box p>0.05 po N iteracjach), a GC-driven energy spikes mają wpływ >5% na medianę energii bez filtrowania — co uzasadnia dedykowany protokół warm-up+GC dla JS energy benchmarking.
Dane:
- Dataset: własne pomiary energia vs iteracja (N=100 powtórzeń per runtime, CPU-bound workload)
- Podział: szereg czasowy energii [J] per iteracja
- Preprocessing: brak (surowe pomiary RAPL)
Metoda:
- Pomiar 100 kolejnych wywołań workloadu SHA256 per runtime (bez restartu procesu)
- Zapis energii [J] per wywołanie → szereg czasowy E(t)
- Ljung-Box test na autocorrelation: kiedy seria staje się stacjonarna? (→ minimalne N warm-up)
- Detekcja GC spikes: identyfikacja wartości odstających (IQR × 1.5) → oblicz % wpływu na medianę
- Porównanie metod pomiaru: RAPL via
perf statvs PowerJoular vs szacowanie CPU-seconds×TDP - Walidacja cross-method: korelacja Pearsona (RAPL vs PowerJoular, oczekiwane R²>0.95)
- Rezultat: protokół eksperymentalny (PDF + repozytorium GitHub)
Modele / Baseline:
| Model | Opis |
|---|---|
| Bez warm-up (N=0) | standard naive approach |
| N=5 warm-up | konwencja z literatury |
| N=10 warm-up | hipoteza: minimum dla V8 |
| N=15 warm-up | konserwatywny |
Metryki:
- Główna: minimalne N warm-up dla stacjonarności (próg: Ljung-Box p>0.05)
- Dodatkowe: % wpływ GC spikes na medianę, R² (RAPL vs PowerJoular)
- Test statystyczny: Ljung-Box (α=0.05), Pearson R²
Wyniki: (do wypełnienia po wykonaniu)
| Runtime | Min warm-up N | GC spike impact [%] | RAPL vs PJ R² |
|---|
Wnioski: (do wypełnienia po wykonaniu)
JE-EXP-3: Model Decyzyjny TOPSIS — Energia × Latencja × Koszt dla Runtime Selection
Status: planned
Priorytet: high
Powiązany pomysł: JE-2
Dodano: 2026-05-27
Hipoteza: Model TOPSIS z wagami energia:latencja:koszt = 0.5:0.3:0.2 rekomenduje inny runtime niż model oparty wyłącznie na latencji w co najmniej 30% kombinacji (workload × platforma) — wykazując, że optymalizacja bez wymiaru energetycznego prowadzi do suboptimalnych wyborów z perspektywy sustainability.
Dane:
- Dataset: wyniki z JE-EXP-1 + dodatkowe pomiary na AWS Lambda i Cloudflare Workers
- Podział: przestrzeń decyzyjna: 3 runtimes × 3 platformy × 6 workload kategorii × 2 stany (cold/warm)
- Preprocessing: normalizacja metryk do [0,1] dla TOPSIS
Metoda:
- Uzupełnienie danych: pomiary na AWS Lambda (Node.js, Deno-layer) + Cloudflare Workers (Node.js compat)
- Implementacja TOPSIS: 4 metryki: E [J/req], latencja_p50 [ms], cold_start [ms], koszt [$/M req]
- Analiza wrażliwości: jak zmiana wag (energia ∈ [0.1, 0.9]) zmienia ranking runtimów?
- Porównanie: TOPSIS(energy) vs TOPSIS(latency-only) — ile przypadków daje inny wybór?
- Walidacja: 5 case studies (Next.js SSR, REST API, edge middleware, background job, streaming)
Modele / Baseline:
| Model | Opis |
|---|---|
| Latency-only ranking | konwencjonalne podejście |
| TOPSIS (energy only) | optymalizacja energy |
| TOPSIS (energy:lat:cost = 0.5:0.3:0.2) | proponowany model |
| TOPSIS (equal weights) | neutralny punkt odniesienia |
Metryki:
- Główna: % przypadków gdzie TOPSIS(energy) ≠ latency-only (próg: >30%)
- Dodatkowe: carbon footprint [gCO₂/req], sensitivity index wag, Kendall tau (ranking stabilność)
- Test statystyczny: McNemar test (proporcja różnych rekomendacji, α=0.05)
Wyniki: (do wypełnienia po wykonaniu)
| Wagi energii | % różnych rekomendacji | Preferowany runtime CPU-bound | Preferowany runtime I/O-bound |
|---|
Wnioski: (do wypełnienia po wykonaniu)
JE-EXP-4: Marginal Energy Attribution dla JS Runtimeów pod Concurrent Load
Status: planned
Priorytet: high
Powiązany pomysł: JE-10
Dodano: 2026-05-28
Hipoteza: Ranking energetyczny runtimeów JS mierzony metodą marginal energy (pomiar przy N+1 funkcjach minus pomiar przy N) różni się od rankingu z izolowanych pomiarów dla workloadów I/O-bound (H10a), a Bun osiąga najniższy marginalny footprint energetyczny pod concurrent load (H10c) — co oznacza, że metodologia FaasMeter [17] jest niezbędna dla rzetelnego porównania runtimeów w multi-tenant FaaS.
Dane:
- Dataset: własne pomiary — scenariusze N=1, 2, 4, 8, 16 współbieżnych instancji per runtime
- Podział: 30 powtórzeń per (runtime × N × workload), łącznie ~1350 pomiarów
- Preprocessing: marginal_E(N) = E(N instancji) − E(N−1 instancji); normalizacja do J/request
Metoda:
- Baseline: izolowane pomiary (#JE-EXP-1) — jeden runtime, jeden workload, brak rywalizacji
- Multi-tenant: uruchom N równoległych instancji tego samego runtimes → zmierz całkowitą energię systemu
- Oblicz marginal energy per instancję jako różnicową miarę (wzorzec z FaasMeter)
- Powtórz dla N = {1, 2, 4, 8, 16} per (runtime × workload)
- Porównaj ranking marginal vs isolated dla CPU-bound i I/O-bound
- Test: Mann-Whitney U między rankingami (H10a: czy porządek zmienia się dla I/O-bound?)
Modele / Baseline:
| Model | Opis |
|---|---|
| Isolated measurement | JE-EXP-1 wyniki (baseline naive) |
| Marginal energy (FaasMeter) | różnicowa atrybucja — podejście referencyjne |
| CPU-governor scaling | kontrola: turbo boost off, governor=performance |
Metryki:
- Główna: ranking Kendall tau (isolated vs marginal) dla CPU-bound i I/O-bound
- Dodatkowe: marginal energy per J/request per N, % odchylenie od isolated measurement
- Test statystyczny: Kendall tau (ranking stabilność), Mann-Whitney U (α=0.05)
Wyniki: (do wypełnienia po wykonaniu)
| N instancji | Node.js marginal [J] | Deno marginal [J] | Bun marginal [J] | ranking = isolated? |
|---|
Wnioski: (do wypełnienia po wykonaniu)
JE-EXP-5: Pomiar E_cold i λ_idle dla Node.js/Deno/Bun — Rozszerzenie Modelu LACE-RL
Status: planned
Priorytet: medium
Powiązany pomysł: JE-11
Dodano: 2026-05-28
Hipoteza: Parametry modelu LACE-RL (E_cold = P_cold × T_cold i λ_idle = P_idle/P_active) różnią się istotnie między JS runtimeami — Bun ma niższe E_cold (H11a) i niższe λ_idle (H11b) niż Node.js — co implikuje różne optymalne progi keep-alive per runtime w środowiskach carbon-aware FaaS.
Dane:
- Dataset: własne pomiary (wymagane hardware: Intel CPU z RAPL, Ubuntu 24.04)
- Podział: 50 cold start pomiarów per runtime (wymagany restart kontenera między próbami) + 30 × 60s pomiarów idle power
- Preprocessing: E_cold = ∫P(t)dt od spawnu do first-response; λ_idle = median(P_idle) / median(P_active)
Metoda:
- Cold start energy (E_cold): pełny restart procesu runtimes między pomiarami; mierz czas + energię od t=0 do first response; PowerJoular 1s granularity (integracja trapezoidalna)
- Idle power (P_idle): uruchom runtime bez żadnych requestów przez 60s → zmierz bazowy pobór mocy (RAPL PACKAGE+DRAM)
- Active power (P_active): steady-state warm execution (po JIT stabilizacji) → P z JE-EXP-1
- λ_idle kalkulacja: λ_idle = P_idle/P_active dla każdego runtimes; 95% CI przez bootstrap
- Analiza: dla jakich wartości λ_idle i E_cold model LACE-RL preferuje krótsze vs dłuższe keep-alive?
- Symulacja: podstaw zmierzone wartości do modelu LACE-RL → jak zmienia się optymalny TTL per runtime?
Modele / Baseline:
| Model | Opis |
|---|---|
| LACE-RL defaults (λ_idle=0.2) | oryginalne wartości z Sun et al. 2026 |
| Node.js empiryczne (λ_idle, E_cold) | zmierzone wartości |
| Deno empiryczne | zmierzone wartości |
| Bun empiryczne | zmierzone wartości |
Metryki:
- Główna: E_cold [J] per runtime (hipoteza: Bun < Node.js), λ_idle per runtime (hipoteza: Bun < Node.js)
- Dodatkowe: 95% CI E_cold przez bootstrap, P_idle [W], P_active [W], cold start T_cold [ms]
- Test statystyczny: Mann-Whitney U (E_cold Bun vs Node.js), Kruskal-Wallis (3 runtimes)
Wyniki: (do wypełnienia po wykonaniu)
| Runtime | E_cold [J] | T_cold [ms] | P_idle [W] | P_active [W] | λ_idle |
|---|---|---|---|---|---|
| Node.js 24 LTS | |||||
| Deno 2.x | |||||
| Bun 1.x |
Wnioski: (do wypełnienia po wykonaniu)
Środowisko pomiarowe (rzeczywiste)
Serwer
| Parametr | Wartość |
|---|---|
| Dostawca | Hetzner Robot (Dedicated Servers Auction) |
| Auction ID | 3003158 |
| CPU | Intel Core i7-6700 (Skylake, 4C/8T, 4.0 GHz Turbo) |
| Generacja CPU | 6. generacja (Skylake, 2015) — RAPL dostępny od Sandy Bridge (2011) |
| RAM | 4 × 16 384 MB DDR4 = 64 GB |
| Storage | 2 × SSD M.2 NVMe 512 GB (Samsung MZVLB512HAJQ) |
| NIC | 1 Gbit Intel I219-LM |
| Traffic | Unlimited |
| IP | 138.201.19.49 |
| Hostname | je-benchmark |
| OS | Ubuntu 24.04.4 LTS (Noble Numbat), zainstalowany 2026-05-28 |
| Kernel | 6.8.0-100-generic |
Konfiguracja pomiarowa
| Ustawienie | Wartość | Cel |
|---|---|---|
| CPU Governor | performance | stabilna częstotliwość zegara |
| Turbo Boost | OFF (/sys/devices/system/cpu/intel_pstate/no_turbo = 1) | eliminacja zmienności TDP |
| Swap | 8 GB (NVMe) | bez OOM killer podczas memory workloadów |
| ASLR | domyślny (on) | nie wymagało zmiany |
Domeny RAPL (potwierdzone)
/sys/class/powercap/intel-rapl:0 → CPU Package (suma wszystkich)
/sys/class/powercap/intel-rapl:0:0 → PP0 Core (tylko rdzenie)
/sys/class/powercap/intel-rapl:0:1 → Uncore (GPU integrated, LLC)
/sys/class/powercap/intel-rapl:0:2 → PP1 / dodatkowe (zależy od SKU)
Pomiar energii: odczyt energy_uj przed i po wykonaniu workloadu → delta → przeliczenie µJ → J.
Obsługa wraparound: gdy delta < 0, użyj max_energy_range_uj do korekty.
Wersje runtimeów (zainstalowane 2026-05-28)
| Runtime | Wersja | Silnik JS | Źródło instalacji |
|---|---|---|---|
| Node.js | v24.15.0 | V8 | NodeSource apt repo (setup_24.x) |
| Deno | 2.8.1 | V8 | deno.land/install.sh |
| Bun | 1.3.14 | JavaScriptCore (WebKit) | bun.sh/install |
| Python | 3.12.3 | — | system Ubuntu |
Uwaga o generacji CPU
Serwer używa i7-6700 (Skylake, 6. gen) zamiast planowanego i5-13500 (Raptor Lake, 13. gen). Implikacje:
- RAPL działa identycznie (dostępny od Sandy Bridge)
- i7-6700 ma 2 domeny RAPL mniej niż Raptor Lake (brak DRAM jako osobna domena)
- Wyniki energetyczne nie są porównywalne z nowszymi platformami — artykuł powinien podkreślać różnice względne (Bun vs Node.js na tej samej platformie), nie wartości bezwzględne [W]
- Do dyskusji w sekcji Threats to Validity: “single hardware platform”
Pipeline danych
Brak zewnętrznych datasets — wszystkie dane generowane własnym benchmark suite. Środowisko pomiarowe: dedykowany bare-metal serwer Intel (Ubuntu 24.04, CPU governor=performance, wyłączony turbo boost dla reprodukowalności). Pomiar energii przez RAPL sysfs (energy_uj delta). Orchestrator Bash uruchamia każdy workload 30+5 razy i zbiera pary (czas, energia, pamięć).
Wymagania techniczne
Środowisko
Python: 3.12+
OS: Ubuntu 24.04 LTS (bare-metal, Intel CPU z RAPL support)
Node.js: 24 LTS
Deno: 2.x (--allow-all dla process.env)
Bun: 1.x
RAM: min. 8 GB (workloady memory-intensive)
Kluczowe biblioteki
# requirements-research.txt
powerjoular>=0.7 # process-level energy measurement
scipy>=1.11 # Mann-Whitney, Ljung-Box
statsmodels>=0.14 # time series tests
pandas>=2.0
topsis-python>=1.1 # MCDM decision model
# npm packages (workload scripts)
# bun/deno: native
Status eksperymentów
| ID | Tytuł | Status | Priorytet | ETA | Wynik |
|---|---|---|---|---|---|
| JE-EXP-1 | Energia Node.js vs Deno vs Bun — 6 workloadów | in_progress | high | 2026-05-28 ~23:00 | — |
| JE-EXP-2 | Standaryzacja metodologii pomiaru energii JS | in_progress | high | 2026-05-28 ~19:00 | — |
| JE-EXP-3 | TOPSIS model decyzyjny energia×latencja×koszt | planned | high | po EXP-1 | — |
| JE-EXP-4 | Marginal energy attribution pod concurrent load | planned | high | — | — |
| JE-EXP-5 | E_cold i λ_idle per runtime — model LACE-RL | planned | medium | — | — |
Przebieg uruchomienia (2026-05-28)
18:56 CEST — tmux 'benchmark' uruchomiony na je-benchmark (138.201.19.49)
18:56 — EXP-2 CPU warmup: node ✓, deno ✗ (brak --allow-env) → crash
19:56 — Fix: deno run --allow-all, restart eksperymentów
19:56 — EXP-2 CPU warmup node: IN PROGRESS
~20:30 — EXP-2 zakończony (szac.)
~20:45 — EXP-1 start (30 reps × 5 workloadów × 3 runtimes × ~30s + cooldown 30s)
~23:00 — EXP-1 zakończony (szac.)
~23:15 — EXP-3 TOPSIS + analiza + wykresy