mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
feat(producer): host/render telemetry in RenderPerfSummary (#1551)
Adds a `host` block (platform, arch, cpuCount, totalMemMb, nodeVersion, gpuDisabled) to RenderPerfSummary so fleet-wide telemetry can correlate render performance with the machine it ran on — chiefly cpuCount vs the existing `workers` field (core over/under-subscription) and totalMemMb vs lowMemoryMode / single-worker collapse. Capture mode + GPU mode already surface via `observability`; this fills in the missing host facts. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1ff99a50f5
commit
7e3bcd9ef1
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { roundDb } from "./perfSummary.js";
|
||||
import { buildRenderPerfSummary, roundDb } from "./perfSummary.js";
|
||||
import type { RenderJob } from "../renderOrchestrator.js";
|
||||
|
||||
describe("roundDb", () => {
|
||||
it("rounds to 1 decimal", () => {
|
||||
@@ -20,3 +21,46 @@ describe("roundDb", () => {
|
||||
expect(roundDb(roundDb(28.4373))).toBe(28.4);
|
||||
});
|
||||
});
|
||||
|
||||
// ponytail: minimal stub — only the fields buildRenderPerfSummary reads are real.
|
||||
const baseInput = {
|
||||
job: { id: "r1", config: { fps: { num: 30, den: 1 }, quality: "high" } } as unknown as RenderJob,
|
||||
workerCount: 4,
|
||||
enableChunkedEncode: false,
|
||||
chunkedEncodeSize: 0,
|
||||
compositionDurationSeconds: 5,
|
||||
totalFrames: 150,
|
||||
outputWidth: 1920,
|
||||
outputHeight: 1080,
|
||||
videoCount: 0,
|
||||
audioCount: 0,
|
||||
totalElapsedMs: 1234,
|
||||
perfStages: {},
|
||||
videoExtractBreakdown: undefined,
|
||||
tmpPeakBytes: 0,
|
||||
captureAttempts: [],
|
||||
hdrDiagnostics: { videoExtractionFailures: 0, imageDecodeFailures: 0 },
|
||||
peakRssBytes: 0,
|
||||
peakHeapUsedBytes: 0,
|
||||
dedupPerfs: [],
|
||||
};
|
||||
|
||||
describe("buildRenderPerfSummary host telemetry", () => {
|
||||
it("captures host facts and threads gpuDisabled through", () => {
|
||||
const summary = buildRenderPerfSummary({ ...baseInput, gpuDisabled: true });
|
||||
expect(summary.host).toBeDefined();
|
||||
expect(summary.host?.gpuDisabled).toBe(true);
|
||||
expect(summary.host?.cpuCount).toBeGreaterThan(0);
|
||||
expect(summary.host?.totalMemMb).toBeGreaterThan(0);
|
||||
expect(summary.host?.platform).toBe(process.platform);
|
||||
expect(summary.host?.arch).toBe(process.arch);
|
||||
expect(summary.host?.nodeVersion).toBe(process.version);
|
||||
});
|
||||
|
||||
it("reflects gpuDisabled=false", () => {
|
||||
const summary = buildRenderPerfSummary({ ...baseInput, gpuDisabled: false });
|
||||
expect(summary.host?.gpuDisabled).toBe(false);
|
||||
// workers vs cores is the headline correlation — both must be present.
|
||||
expect(summary.workers).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* the `perf-summary.json` debug artifact.
|
||||
*/
|
||||
|
||||
import { arch, cpus, platform, totalmem } from "node:os";
|
||||
import { fpsToNumber } from "@hyperframes/core";
|
||||
import type { CapturePerfSummary, SubTimelineWaitOutcome, WorkerSizing } from "@hyperframes/engine";
|
||||
import type { CaptureCalibrationSample, CaptureCostEstimate } from "./captureCost.js";
|
||||
@@ -221,6 +222,8 @@ export function buildRenderPerfSummary(input: {
|
||||
/** Per-session/per-worker static-dedup perf; aggregated into `staticDedup`. */
|
||||
dedupPerfs: CapturePerfSummary[];
|
||||
drawElement?: DrawElementPerfInput;
|
||||
/** `cfg.disableGpu` — the hard `--disable-gpu` flag, for the `host` GPU picture. */
|
||||
gpuDisabled: boolean;
|
||||
}): RenderPerfSummary {
|
||||
return {
|
||||
renderId: input.job.id,
|
||||
@@ -282,5 +285,13 @@ export function buildRenderPerfSummary(input: {
|
||||
input.dedupPerfs,
|
||||
input.drawElement ?? { selfVerifyFallback: false },
|
||||
),
|
||||
host: {
|
||||
platform: platform(),
|
||||
arch: arch(),
|
||||
cpuCount: cpus().length,
|
||||
totalMemMb: Math.round(totalmem() / (1024 * 1024)),
|
||||
nodeVersion: process.version,
|
||||
gpuDisabled: input.gpuDisabled,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -546,6 +546,27 @@ export interface RenderPerfSummary {
|
||||
/** Per-frame "No cached paint record" screenshot fallbacks. */
|
||||
ncprFallbacks: number;
|
||||
};
|
||||
/**
|
||||
* Render-host facts, captured from the orchestrator process. Lets fleet-wide
|
||||
* telemetry correlate render performance with the machine it ran on — most
|
||||
* importantly `cpuCount` vs the top-level `workers` (are we under-/over-
|
||||
* subscribing cores?) and `totalMemMb` (does `lowMemoryMode` / single-worker
|
||||
* collapse track real memory pressure?). `gpuDisabled` completes the GPU
|
||||
* picture alongside `observability.browserGpuMode`.
|
||||
*
|
||||
* Reflects the ORCHESTRATOR host. For distributed renders the chunk workers
|
||||
* may run on different machines; this is still the right signal for the
|
||||
* common single-machine render. Optional for back-compat with serialized
|
||||
* older summaries.
|
||||
*/
|
||||
host?: {
|
||||
platform: string;
|
||||
arch: string;
|
||||
cpuCount: number;
|
||||
totalMemMb: number;
|
||||
nodeVersion: string;
|
||||
gpuDisabled: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface HdrDiagnostics {
|
||||
@@ -3971,6 +3992,7 @@ async function executeRenderPipeline(input: {
|
||||
observability: observabilitySummary,
|
||||
peakRssBytes: memSampler.peakRssBytes(),
|
||||
peakHeapUsedBytes: memSampler.peakHeapUsedBytes(),
|
||||
gpuDisabled: cfg.disableGpu,
|
||||
});
|
||||
job.perfSummary = perfSummary;
|
||||
if (job.config.debug) {
|
||||
|
||||
Reference in New Issue
Block a user