diff --git a/src/__tests__/unit/lib/teads-curve/index.test.ts b/src/__tests__/unit/lib/teads-curve/index.test.ts index 1d6ce62..cfedfd3 100644 --- a/src/__tests__/unit/lib/teads-curve/index.test.ts +++ b/src/__tests__/unit/lib/teads-curve/index.test.ts @@ -26,6 +26,32 @@ describe('teads:configure test', () => { }, ]); }); + test('scale with vcpu usage', async () => { + const outputModel = new TeadsCurveModel(); + await outputModel.configure({ + 'thermal-design-power': 200, + }); + await expect( + outputModel.execute([ + { + duration: 3600, + 'cpu-util': 50.0, + timestamp: '2021-01-01T00:00:00Z', + 'vcpus-allocated': 1, + 'vcpus-total': 64, + }, + ]) + ).resolves.toStrictEqual([ + { + 'energy-cpu': 0.00234375, + duration: 3600, + 'cpu-util': 50.0, + timestamp: '2021-01-01T00:00:00Z', + 'vcpus-allocated': 1, + 'vcpus-total': 64, + }, + ]); + }); test('teads:initialize with params:spline', async () => { const outputModel = new TeadsCurveModel(); await outputModel.configure({ diff --git a/src/lib/teads-curve/README.md b/src/lib/teads-curve/README.md index 196e035..e9e2433 100644 --- a/src/lib/teads-curve/README.md +++ b/src/lib/teads-curve/README.md @@ -25,6 +25,10 @@ IF recognizes the Teads CPU model as `teads-curve`. - `energy-cpu`: The energy used by the CPU, in kWh +> **Note** If `vcpus-allocated` and `vcpus-total` are available, these data will be used to scale the CPU energy usage. If they are not present, we assume the entire processor is being used. For example, if only 1 out of 64 available vCPUS are allocated, we scale the processor TDP by 1/64. + + + ## Implementation ### Linear Interpolation diff --git a/src/lib/teads-curve/index.ts b/src/lib/teads-curve/index.ts index 6462a1e..4d25b4f 100644 --- a/src/lib/teads-curve/index.ts +++ b/src/lib/teads-curve/index.ts @@ -37,17 +37,6 @@ export class TeadsCurveModel implements ModelPluginInterface { this.tdp = staticParams['thermal-design-power'] as number; } - // if ('curve' in staticParams && 'points' in staticParams) { - // this.curve = staticParams?.curve as number[]; - // this.points = staticParams?.points as number[]; - // if (this.curve.length !== this.points.length) { - // throw new Error( - // 'Number of points and curve values must be the same length' - // ); - // } - // this.spline = new Spline(this.points, this.curve); - // } - if ('interpolation' in staticParams) { this.interpolation = staticParams?.interpolation as Interpolation; } @@ -72,7 +61,29 @@ export class TeadsCurveModel implements ModelPluginInterface { } return inputs.map((input: KeyValuePair) => { this.configure(input); - input['energy-cpu'] = this.calculateEnergy(input); + let energy = this.calculateEnergy(input); + let total: number; + let allocated: number; + if ('vcpus-allocated' in input && 'vcpus-total' in input) { + if (typeof input['vcpus-allocated'] === 'string') { + allocated = parseFloat(input['vcpus-allocated']); + } else if (typeof input['vcpus-allocated'] === 'number') { + allocated = input['vcpus-allocated']; + } else { + throw new Error('invalid type for vcpus-allocated'); + } + + if (typeof input['vcpus-total'] === 'string') { + total = parseFloat(input['vcpus-total']); + } else if (typeof input['vcpus-total'] === 'number') { + total = input['vcpus-total']; + } else { + throw new Error('invalid type for vcpus-total'); + } + + energy = energy * (allocated / total); + } + input['energy-cpu'] = energy; return input; }); }