Skip to content

Commit a3e8424

Browse files
authored
feat: v0.7.0 — memory power draw (CPU + memory watts per CCF standard), 3 new tests (#16)
1 parent d56e3d4 commit a3e8424

9 files changed

Lines changed: 234 additions & 135 deletions

File tree

METHODOLOGY.md

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,22 @@ Run `greenops-cli --coverage` to see the full instance and region list per provi
3434

3535
### Power Model
3636

37-
GreenOps uses the **linear interpolation model** from the Cloud Carbon Footprint (CCF) methodology:
37+
GreenOps uses the **linear interpolation model** from the Cloud Carbon Footprint (CCF) methodology, extended with memory power draw:
3838

3939
```
40-
W_effective = W_idle + (W_max - W_idle) × utilization
40+
W_cpu = W_idle + (W_max - W_idle) × utilization
41+
W_memory = memory_gb × 0.392 W/GB
42+
W_effective = W_cpu + W_memory
4143
```
4244

4345
Where:
4446
- `W_idle` = idle TDP (watts) from `factors.json`
4547
- `W_max` = maximum TDP (watts) from `factors.json`
4648
- `utilization` = CPU utilisation fraction (default: 0.50, matching CCF baseline)
49+
- `memory_gb` = RAM size from `factors.json`
50+
- `0.392 W/GB` = CCF memory power coefficient (constant, not utilization-dependent)
51+
52+
Memory power draw is **constant** regardless of CPU utilisation. This reflects that DRAM draws near-constant power whether or not it is actively being written to, consistent with CCF v3 methodology.
4753

4854
### Carbon Calculation
4955

@@ -64,21 +70,27 @@ GCP's 1.10 PUE is the best in class among the three major providers, producing ~
6470

6571
### Worked Example — AWS m5.large in us-east-1 at 50% utilisation
6672

67-
1. **Power:** `W = 6.8 + (20.4 - 6.8) × 0.50 = 13.6W`
68-
2. **Energy:** `13.6W × 1.13 PUE × 730h / 1000 = 11.219 kWh/month`
69-
3. **Carbon:** `11.219 × 384.5 = 4,313.6g CO2e/month`
73+
1. **CPU power:** `W_cpu = 6.8 + (20.4 - 6.8) × 0.50 = 13.6W`
74+
2. **Memory power:** `W_mem = 8GB × 0.392 = 3.136W`
75+
3. **Total:** `W = 13.6 + 3.136 = 16.736W`
76+
4. **Energy:** `16.736W × 1.13 PUE × 730h / 1000 = 13.816 kWh/month`
77+
5. **Carbon:** `13.816 × 384.5 = 5,308.2g CO2e/month`
7078

7179
### Worked Example — Azure Standard_D2s_v3 in eastus at 50% utilisation
7280

73-
1. **Power:** `W = 6.8 + (20.4 - 6.8) × 0.50 = 13.6W`
74-
2. **Energy:** `13.6W × 1.125 PUE × 730h / 1000 = 11.178 kWh/month`
75-
3. **Carbon:** `11.178 × 380.0 = 4,244.2g CO2e/month`
81+
1. **CPU power:** `W_cpu = 6.8 + (20.4 - 6.8) × 0.50 = 13.6W`
82+
2. **Memory power:** `W_mem = 8GB × 0.392 = 3.136W`
83+
3. **Total:** `W = 16.736W`
84+
4. **Energy:** `16.736W × 1.125 PUE × 730h / 1000 = 13.745 kWh/month`
85+
5. **Carbon:** `13.745 × 380.0 = 5,222.9g CO2e/month`
7686

7787
### Worked Example — GCP n2-standard-2 in us-central1 at 50% utilisation
7888

79-
1. **Power:** `W = 6.8 + (20.4 - 6.8) × 0.50 = 13.6W`
80-
2. **Energy:** `13.6W × 1.10 PUE × 730h / 1000 = 10.921 kWh/month`
81-
3. **Carbon:** `10.921 × 340.0 = 3,713.1g CO2e/month`
89+
1. **CPU power:** `W_cpu = 6.8 + (20.4 - 6.8) × 0.50 = 13.6W`
90+
2. **Memory power:** `W_mem = 8GB × 0.392 = 3.136W`
91+
3. **Total:** `W = 16.736W`
92+
4. **Energy:** `16.736W × 1.10 PUE × 730h / 1000 = 13.445 kWh/month`
93+
5. **Carbon:** `13.445 × 340.0 = 4,569.3g CO2e/month`
8294

8395
---
8496

dist/index.cjs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,7 +1968,7 @@ var factors_default = {
19681968
// package.json
19691969
var package_default = {
19701970
name: "greenops-cli",
1971-
version: "0.6.0",
1971+
version: "0.7.0",
19721972
description: "Carbon footprint linting for Terraform plans \u2014 AWS, Azure, and GCP. Analyses infrastructure changes for Scope 2, Scope 3, and water impact. Posts recommendations directly on GitHub PRs.",
19731973
main: "dist/index.cjs",
19741974
bin: {
@@ -2241,6 +2241,7 @@ function extractResourceInputs(planFilePath) {
22412241
// engine.ts
22422242
var HOURS_PER_MONTH = 730;
22432243
var GRAMS_PER_KWH = 1e3;
2244+
var MEMORY_WATTS_PER_GB = 0.392;
22442245
function resolveUtilization(input, ledger) {
22452246
if (input.avgUtilization !== void 0 && (input.avgUtilization < 0 || input.avgUtilization > 1)) {
22462247
throw new RangeError(`avgUtilization must be between 0 and 1, got ${input.avgUtilization}`);
@@ -2250,8 +2251,10 @@ function resolveUtilization(input, ledger) {
22502251
}
22512252
return input.avgUtilization ?? ledger.metadata.assumptions.default_utilization.value;
22522253
}
2253-
function linearInterpolationWatts(idle, max, utilization) {
2254-
return idle + (max - idle) * utilization;
2254+
function effectiveTotalWatts(idle, max, utilization, memoryGb) {
2255+
const cpuWatts = idle + (max - idle) * utilization;
2256+
const memoryWatts = memoryGb * MEMORY_WATTS_PER_GB;
2257+
return cpuWatts + memoryWatts;
22552258
}
22562259
function wattsToScope2Carbon(watts, hours, pue, gridIntensity) {
22572260
return watts * pue * hours / GRAMS_PER_KWH * gridIntensity;
@@ -2333,7 +2336,8 @@ function calculateBaseline(input, ledger = factors_default) {
23332336
gridIntensityApplied: gridIntensity,
23342337
powerModelUsed: "LINEAR_INTERPOLATION",
23352338
embodiedCo2ePerVcpuPerMonthApplied: embodied,
2336-
waterIntensityLitresPerKwhApplied: waterIntensity
2339+
waterIntensityLitresPerKwhApplied: waterIntensity,
2340+
memoryWattsApplied: 0
23372341
}
23382342
});
23392343
const regionData = providerLedger.regions[input.region];
@@ -2359,10 +2363,11 @@ function calculateBaseline(input, ledger = factors_default) {
23592363
);
23602364
}
23612365
const powerModel = "LINEAR_INTERPOLATION";
2362-
const effectiveWatts = linearInterpolationWatts(
2366+
const effectiveWatts = effectiveTotalWatts(
23632367
instanceData.power_watts.idle,
23642368
instanceData.power_watts.max,
2365-
utilization
2369+
utilization,
2370+
instanceData.memory_gb
23662371
);
23672372
const totalCo2eGramsPerMonth = wattsToScope2Carbon(
23682373
effectiveWatts,
@@ -2388,7 +2393,8 @@ function calculateBaseline(input, ledger = factors_default) {
23882393
gridIntensityApplied: regionData.grid_intensity_gco2e_per_kwh,
23892394
powerModelUsed: powerModel,
23902395
embodiedCo2ePerVcpuPerMonthApplied: instanceData.embodied_co2e_grams_per_month,
2391-
waterIntensityLitresPerKwhApplied: regionData.water_intensity_litres_per_kwh
2396+
waterIntensityLitresPerKwhApplied: regionData.water_intensity_litres_per_kwh,
2397+
memoryWattsApplied: instanceData.memory_gb * MEMORY_WATTS_PER_GB
23922398
}
23932399
};
23942400
}

0 commit comments

Comments
 (0)