feat: add combineSeries for GPU combination aggregation
This commit is contained in:
@@ -22,6 +22,18 @@ const AGGREGATE: Record<GpuMetricKind, (values: number[]) => number> = {
|
|||||||
fan: avg,
|
fan: avg,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function combineSeries(histories: number[][], kind: GpuMetricKind): { value?: number; history: number[] } {
|
||||||
|
const n = Math.max(...histories.map((h) => h.length), 0);
|
||||||
|
if (n === 0) return { value: undefined, history: [] };
|
||||||
|
const history: number[] = [];
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const at = histories.map((h) => h[i]).filter((v): v is number => v !== undefined);
|
||||||
|
if (at.length === 0) continue;
|
||||||
|
history.push(AGGREGATE[kind](at));
|
||||||
|
}
|
||||||
|
return { value: history.length > 0 ? history[history.length - 1] : undefined, history };
|
||||||
|
}
|
||||||
|
|
||||||
function key(gpuId: string, kind: GpuMetricKind): string {
|
function key(gpuId: string, kind: GpuMetricKind): string {
|
||||||
return `${gpuId}|${kind}`;
|
return `${gpuId}|${kind}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import assert from "node:assert/strict";
|
|||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
import { test } from "node:test";
|
import { test } from "node:test";
|
||||||
import { type LlamaSwapConfig } from "../src/lib/util";
|
import { type LlamaSwapConfig } from "../src/lib/util";
|
||||||
import { MetricsPoller } from "../src/lib/metrics-poller";
|
import { combineSeries, MetricsPoller } from "../src/lib/metrics-poller";
|
||||||
|
|
||||||
|
|
||||||
const FIXTURE = readFileSync(new URL("./fixtures/metrics.txt", import.meta.url), "utf8");
|
const FIXTURE = readFileSync(new URL("./fixtures/metrics.txt", import.meta.url), "utf8");
|
||||||
@@ -61,3 +61,31 @@ test("poller reports offline after a fetch failure and recovers", async () => {
|
|||||||
assert.equal(poller.isOffline(), false);
|
assert.equal(poller.isOffline(), false);
|
||||||
assert.ok(poller.getValue("0", "util_percent") !== undefined);
|
assert.ok(poller.getValue("0", "util_percent") !== undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("combineSeries averages util and sums power", () => {
|
||||||
|
const util = combineSeries(
|
||||||
|
[
|
||||||
|
[10, 20, 30],
|
||||||
|
[20, 40, 60],
|
||||||
|
],
|
||||||
|
"util_percent",
|
||||||
|
);
|
||||||
|
assert.deepEqual(util, { value: 45, history: [15, 30, 45] });
|
||||||
|
|
||||||
|
const power = combineSeries(
|
||||||
|
[
|
||||||
|
[100, 200],
|
||||||
|
[150, 250],
|
||||||
|
],
|
||||||
|
"power",
|
||||||
|
);
|
||||||
|
assert.deepEqual(power, { value: 450, history: [250, 450] });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("combineSeries takes the max temperature and skips gaps", () => {
|
||||||
|
const temp = combineSeries([[50, 70], [60]], "temperature");
|
||||||
|
assert.deepEqual(temp, { value: 70, history: [60, 70] });
|
||||||
|
|
||||||
|
const empty = combineSeries([[], []], "temperature");
|
||||||
|
assert.deepEqual(empty, { value: undefined, history: [] });
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user