-
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
calculate operational and embodied emissions per segment
- Loading branch information
Showing
3 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
"use strict"; | ||
|
||
/** | ||
* Sustainable Web Design version 4 | ||
* | ||
* Updated calculations and figures from | ||
* https://sustainablewebdesign.org/estimating-digital-emissions/ | ||
* | ||
*/ | ||
|
||
import { fileSize, SWDV4 } from "./constants/index.js"; | ||
import { formatNumber } from "./helpers/index.js"; | ||
|
||
const { | ||
OPERATIONAL_KWH_PER_GB_DATACENTER, | ||
OPERATIONAL_KWH_PER_GB_NETWORK, | ||
OPERATIONAL_KWH_PER_GB_DEVICE, | ||
EMBODIED_KWH_PER_GB_DATACENTER, | ||
EMBODIED_KWH_PER_GB_NETWORK, | ||
EMBODIED_KWH_PER_GB_DEVICE, | ||
GLOBAL_GRID_INTENSITY, | ||
} = SWDV4; | ||
|
||
class SustainableWebDesign { | ||
constructor(options) { | ||
this.options = options; | ||
} | ||
|
||
/** | ||
* Calculate the operational energy of data transfer for each system segment | ||
* | ||
* @param {number} bytes | ||
* @returns {object} | ||
*/ | ||
operationalEnergyPerSegment(bytes) { | ||
const transferedBytesToGb = bytes / fileSize.GIGABYTE; | ||
const dataCenter = transferedBytesToGb * OPERATIONAL_KWH_PER_GB_DATACENTER; | ||
const network = transferedBytesToGb * OPERATIONAL_KWH_PER_GB_NETWORK; | ||
const device = transferedBytesToGb * OPERATIONAL_KWH_PER_GB_DEVICE; | ||
|
||
return { | ||
dataCenter, | ||
network, | ||
device, | ||
}; | ||
} | ||
|
||
/** | ||
* Calculate the operational emissions of data transfer for each system segment | ||
* | ||
* @param {number} bytes | ||
* @param {object} options | ||
* @returns {object} | ||
*/ | ||
operationalEmissions(bytes, options = {}) { | ||
const { dataCenter, network, device } = | ||
this.operationalEnergyPerSegment(bytes); | ||
|
||
let dataCenterGridIntensity = GLOBAL_GRID_INTENSITY; | ||
let networkGridIntensity = GLOBAL_GRID_INTENSITY; | ||
let deviceGridIntensity = GLOBAL_GRID_INTENSITY; | ||
|
||
if (options?.gridIntensity) { | ||
const { device, network, dataCenter } = options.gridIntensity; | ||
|
||
if (device?.value || device?.value === 0) { | ||
deviceGridIntensity = device.value; | ||
} | ||
|
||
if (network?.value || network?.value === 0) { | ||
networkGridIntensity = network.value; | ||
} | ||
|
||
if (dataCenter?.value || dataCenter?.value === 0) { | ||
dataCenterGridIntensity = dataCenter.value; | ||
} | ||
} | ||
|
||
const dataCenterEmissions = dataCenter * dataCenterGridIntensity; | ||
const networkEmissions = network * networkGridIntensity; | ||
const deviceEmissions = device * deviceGridIntensity; | ||
|
||
return { | ||
dataCenter: dataCenterEmissions, | ||
network: networkEmissions, | ||
device: deviceEmissions, | ||
}; | ||
} | ||
|
||
/** | ||
* Calculate the embodied energy of data transfer for each system segment | ||
* | ||
* @param {number} bytes | ||
* @returns {object} | ||
*/ | ||
embodiedEnergyPerSegment(bytes) { | ||
const transferedBytesToGb = bytes / fileSize.GIGABYTE; | ||
const dataCenter = transferedBytesToGb * EMBODIED_KWH_PER_GB_DATACENTER; | ||
const network = transferedBytesToGb * EMBODIED_KWH_PER_GB_NETWORK; | ||
const device = transferedBytesToGb * EMBODIED_KWH_PER_GB_DEVICE; | ||
|
||
return { | ||
dataCenter, | ||
network, | ||
device, | ||
}; | ||
} | ||
|
||
/** | ||
* Calculate the embodied emissions of data transfer for each system segment | ||
* | ||
* @param {number} bytes | ||
* @returns {object} | ||
*/ | ||
embodiedEmissions(bytes) { | ||
const { dataCenter, network, device } = | ||
this.embodiedEnergyPerSegment(bytes); | ||
|
||
const dataCenterGridIntensity = GLOBAL_GRID_INTENSITY; | ||
const networkGridIntensity = GLOBAL_GRID_INTENSITY; | ||
const deviceGridIntensity = GLOBAL_GRID_INTENSITY; | ||
|
||
// NOTE: Per the guidance in the SWDM v4, the grid intensity values for embodied emissions are fixed to the global grid intensity. | ||
|
||
const dataCenterEmissions = dataCenter * dataCenterGridIntensity; | ||
const networkEmissions = network * networkGridIntensity; | ||
const deviceEmissions = device * deviceGridIntensity; | ||
|
||
return { | ||
dataCenter: dataCenterEmissions, | ||
network: networkEmissions, | ||
device: deviceEmissions, | ||
}; | ||
} | ||
} | ||
|
||
export { SustainableWebDesign }; | ||
export default SustainableWebDesign; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import SustainableWebDesign from "./sustainable-web-design-v4.js"; | ||
import { MILLION, SWDV4 } from "./constants/test-constants.js"; | ||
|
||
describe("sustainable web design model version 4", () => { | ||
const swd = new SustainableWebDesign(); | ||
|
||
describe("operational emissions", () => { | ||
it("returns the expected emissions for 1GB data transfer", () => { | ||
const result = swd.operationalEmissions(1000000000); | ||
expect(result).toEqual( | ||
expect.objectContaining({ | ||
dataCenter: expect.any(Number), | ||
network: expect.any(Number), | ||
device: expect.any(Number), | ||
}) | ||
); | ||
expect(result.dataCenter).toBeCloseTo(27.17, 3); | ||
expect(result.network).toBeCloseTo(29.146, 3); | ||
expect(result.device).toBeCloseTo(39.52, 3); | ||
}); | ||
|
||
it("returns the expected emissions for 0bytes data transfer", () => { | ||
const result = swd.operationalEmissions(0); | ||
expect(result).toEqual( | ||
expect.objectContaining({ | ||
dataCenter: expect.any(Number), | ||
network: expect.any(Number), | ||
device: expect.any(Number), | ||
}) | ||
); | ||
expect(result.dataCenter).toBeCloseTo(0, 3); | ||
expect(result.network).toBeCloseTo(0, 3); | ||
expect(result.device).toBeCloseTo(0, 3); | ||
}); | ||
|
||
if ( | ||
("returns the expected emissions for 1GB data transfer with custom grid intensities", | ||
() => { | ||
const result = swd.operationalEmissions(1000000000, { | ||
gridIntensity: { | ||
dataCenter: { value: 100 }, | ||
network: { value: 200 }, | ||
device: { value: 300 }, | ||
}, | ||
}); | ||
expect(result).toEqual( | ||
expect.objectContaining({ | ||
dataCenter: expect.any(Number), | ||
network: expect.any(Number), | ||
device: expect.any(Number), | ||
}) | ||
); | ||
expect(result.dataCenter).toBeCloseTo(5.5, 3); | ||
expect(result.network).toBeCloseTo(11.8, 3); | ||
expect(result.device).toBeCloseTo(24, 3); | ||
}) | ||
); | ||
}); | ||
|
||
describe("embodied emissions", () => { | ||
it("returns the expected emissions for 1GB data transfer", () => { | ||
const result = swd.embodiedEmissions(1000000000); | ||
expect(result).toEqual( | ||
expect.objectContaining({ | ||
dataCenter: expect.any(Number), | ||
network: expect.any(Number), | ||
device: expect.any(Number), | ||
}) | ||
); | ||
expect(result.dataCenter).toBeCloseTo(5.928, 3); | ||
expect(result.network).toBeCloseTo(6.422, 3); | ||
expect(result.device).toBeCloseTo(40.014, 3); | ||
}); | ||
|
||
it("returns the expected emissions for 0bytes data transfer", () => { | ||
const result = swd.embodiedEmissions(0); | ||
expect(result).toEqual( | ||
expect.objectContaining({ | ||
dataCenter: expect.any(Number), | ||
network: expect.any(Number), | ||
device: expect.any(Number), | ||
}) | ||
); | ||
expect(result.dataCenter).toBeCloseTo(0, 3); | ||
expect(result.network).toBeCloseTo(0, 3); | ||
expect(result.device).toBeCloseTo(0, 3); | ||
}); | ||
}); | ||
}); |