From 6ef0a9c4b56f1497b57423bb8aa8a63a1ec9d613 Mon Sep 17 00:00:00 2001 From: Jareth Main Date: Tue, 2 Apr 2024 17:10:37 +0100 Subject: [PATCH] Create storage read write plugin to estimate energy used when reading and writing data to storages devices --- examples/storage-read-write-energy.yml | 32 ++++++++++++ .../lib/storage-read-write-energy.test.ts | 32 ++++++++++++ src/lib/index.ts | 1 + src/lib/storage-read-write-energy/README.md | 38 ++++++++++++++ src/lib/storage-read-write-energy/index.ts | 51 +++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 examples/storage-read-write-energy.yml create mode 100644 src/__tests__/unit/lib/storage-read-write-energy.test.ts create mode 100644 src/lib/storage-read-write-energy/README.md create mode 100644 src/lib/storage-read-write-energy/index.ts diff --git a/examples/storage-read-write-energy.yml b/examples/storage-read-write-energy.yml new file mode 100644 index 0000000..4d78a9c --- /dev/null +++ b/examples/storage-read-write-energy.yml @@ -0,0 +1,32 @@ +name: basic storage read/write energy example +description: Uses minimal mock data to run the plugin +tags: null +initialize: + plugins: + import-data: + path: '@grnsft/if-plugins' + method: MockObservations + global-config: + timestamp-from: 2024-03-05T00:00 + timestamp-to: 2024-03-05T01:00 + duration: 300 + components: + - name: storage-1 + generators: + randint: + storage/data-transfer: + min: 100 + max: 20000 + storage/drive-read-write-power: + min: 15 + max: 20 + storage/drive-read-write-speed: + min: 1 + max: 6 + object-storage-read-write: + method: StorageReadWriteEnergy + path: 'if-carbon-hack-plugin' +tree: + pipeline: + - import-data + - object-storage-read-write diff --git a/src/__tests__/unit/lib/storage-read-write-energy.test.ts b/src/__tests__/unit/lib/storage-read-write-energy.test.ts new file mode 100644 index 0000000..b109efd --- /dev/null +++ b/src/__tests__/unit/lib/storage-read-write-energy.test.ts @@ -0,0 +1,32 @@ +import {StorageReadWriteEnergy} from '../../../lib/storage-read-write-energy'; + +describe('lib/storage-read-write-energy: ', () => { + describe('StorageReadWriteEnergy(): ', () => { + it('has metadata field.', () => { + const pluginInstance = StorageReadWriteEnergy(); + + expect(pluginInstance).toHaveProperty('metadata'); + expect(pluginInstance).toHaveProperty('execute'); + expect(pluginInstance.metadata).toHaveProperty('kind'); + expect(typeof pluginInstance.execute).toBe('function'); + }); + + describe('execute(): ', () => { + it('calculates kWh of read/write of 1TB of data, at a speed of 5Gb/s, to storage device', async () => { + const pluginInstance = StorageReadWriteEnergy(); + const inputs = [ + { + duration: 200, + 'storage/drive-read-write-power': 20, + 'storage/drive-read-write-speed': 5, + 'storage/data-transfer': 1000, + }, + ]; + + const response = await pluginInstance.execute(inputs, {}); + expect(response[0]).toHaveProperty('storage/energy'); + expect(response[0]['storage/energy']).toBeCloseTo(0.00111, 5); + }); + }); + }); +}); diff --git a/src/lib/index.ts b/src/lib/index.ts index 5ee3db9..3a738d9 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -2,3 +2,4 @@ export {CloudStorageMetadata} from './cloud-storage-metadata'; export {ObjectStorage} from './object-storage'; export {RambollResilio} from './ramboll-resilio'; export {StorageEnergy} from './storage-energy'; +export {StorageReadWriteEnergy} from './storage-read-write-energy'; diff --git a/src/lib/storage-read-write-energy/README.md b/src/lib/storage-read-write-energy/README.md new file mode 100644 index 0000000..5375490 --- /dev/null +++ b/src/lib/storage-read-write-energy/README.md @@ -0,0 +1,38 @@ +# Storage Read Write Energy + +This plugin allows you to estimate the energy required to read/write data to a storage device, amount of data and drive type + +## Parameters + +## Plugin Config + +Not Needed + +### Inputs + +- `duration`: Length of time the it will take to read/write the data +- `storage/drive-read-write-power`: Power of the drive(s), when reading/writing, used in Watts +- `storage/drive-read-write-speed`: Read/write speed of storage device used in Gb/s +- `storage/data-transfer`: Amount of data to be read/written in Gb + +## Returns + +An array containing: + +- `duration`: Length of time the it will take to read/write the data +- `storage/drive-read-write-power`: Power of the drive(s), when reading/writing, used in Watts +- `storage/drive-read-write-speed`: Read/write speed of storage device used in Gb/s +- `storage/data-transfer`: Amount of data to be read/written in Gb +- `storage/energy`: The energy apportioned to reading/writing data in kWh + +## IF Implementation + +To avoid tying the plugin to any point in time data, it requires the individual drive details to be passed in.Calculates the minimum time that that data could be written/read in, using: + +$$drive\text-read\text-write\text-speed \times data\text-transfer = min \space time$$ + +If this is less than the provided duration it will use this instead. The formula for energy estimation is then: + +$$\frac{drive\text-read\text-write\text-power}{1000} \times \frac{duration}{60 \times 60} = energy$$ + +Where $\frac{drive\text-read\text-write\text-power}{1000}$ gives a figure for kW and $\frac{duration}{60 \times 60}$ gives the time in hours. diff --git a/src/lib/storage-read-write-energy/index.ts b/src/lib/storage-read-write-energy/index.ts new file mode 100644 index 0000000..e160103 --- /dev/null +++ b/src/lib/storage-read-write-energy/index.ts @@ -0,0 +1,51 @@ +import {z} from 'zod'; +import {PluginInterface, PluginParams} from '../types/interface'; +import {validate} from '../util/validations'; +import {SECONDS_IN_HOUR} from '../constants'; + +export const StorageReadWriteEnergy = (): PluginInterface => { + const metadata = { + kind: 'execute', + }; + + /** + * Execute's strategy description here. + */ + const execute = async (inputs: PluginParams[]): Promise => { + return inputs.map(input => { + const safeInput = validateInput(input); + const minTime = Math.ceil( + safeInput['storage/data-transfer'] / + safeInput['storage/drive-read-write-speed'] + ); + + const duration = Math.max(safeInput.duration, minTime); + const kW = safeInput['storage/drive-read-write-power'] / 1000; + const durationInHours = duration / SECONDS_IN_HOUR; + + return { + ...input, + 'storage/energy': kW * durationInHours, + }; + }); + }; + + /** + * Checks for required fields in input. + */ + const validateInput = (input: PluginParams) => { + const schema = z.object({ + duration: z.number().positive(), + 'storage/drive-read-write-power': z.number().positive(), + 'storage/drive-read-write-speed': z.number().positive(), + 'storage/data-transfer': z.number().positive(), + }); + + return validate>(schema, input); + }; + + return { + metadata, + execute, + }; +};