fix(producer): guard pmset behind shouldTrack + don't pin workers without streaming (review)

Two review findings on the floor/telemetry PR:

1. powerStateFields() is spread into the properties object at the CALL SITE,
   so it ran before trackEvent's own `if (!shouldTrack()) return` guard —
   telemetry-disabled installs paid two blocking `pmset` subprocess spawns
   per render for an event that was then discarded. Now short-circuits on
   shouldTrack() (memoized, so no cost on the tracked path). Regression test
   asserts pmset is not sampled when telemetry is off; fault-injection
   verified it fails without the guard.

2. The DE parallel router pinned workerCount to 3 and skipped calibration
   even when verified parallel DE STREAMING — the entire reason for the pin
   — could not run for that render. The common case is a composition over
   streamingEncodeMaxDurationSeconds (240 s default): the duration cap
   disables streaming before the router's force flag is consulted, so the
   render got a hard-coded 3 workers chosen by a benchmark for a path it was
   not on, instead of the calibrated count. shouldPreferParallelDrawElement
   now takes parallelStreamingAvailable and withholds the bet without it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-07-28 00:59:22 -07:00
co-authored by Claude Opus 5
parent 3da31e399b
commit b99c803898
4 changed files with 76 additions and 1 deletions
@@ -1842,6 +1842,7 @@ describe("shouldPreferParallelDrawElement (DE parallel router)", () => {
probeDeGated: false,
experimentalParallelDeOptIn: false,
routerEnabled: true,
parallelStreamingAvailable: true,
totalMemoryMb: 32768,
minMemoryMb: 24576,
};
@@ -1850,6 +1851,16 @@ describe("shouldPreferParallelDrawElement (DE parallel router)", () => {
expect(shouldPreferParallelDrawElement(eligible)).toBe(true);
});
it("withholds the bet when parallel streaming can't run (e.g. over the duration cap)", () => {
// The router pins workerCount to 3 and skips calibration to serve the
// verified parallel DE STREAMING path. If streaming is off for this
// render — the >240s duration cap is the common case — firing would pay
// the whole cost of the pin for none of the benefit.
expect(
shouldPreferParallelDrawElement({ ...eligible, parallelStreamingAvailable: false }),
).toBe(false);
});
it("withholds the parallel bet below the RAM floor (16 GB black-slab report)", () => {
expect(shouldPreferParallelDrawElement({ ...eligible, totalMemoryMb: 16384 })).toBe(false);
});
@@ -1331,6 +1331,16 @@ export function shouldPreferParallelDrawElement(args: {
experimentalParallelDeOptIn: boolean;
/** HF_DE_PARALLEL_ROUTER === "true" — the router's own kill switch, default off. */
routerEnabled: boolean;
/**
* Whether verified parallel DE STREAMING can actually run for this render
* (`shouldUseStreamingEncode` at the router's worker count with
* forceParallelStream). The router's entire value is that path; without it
* firing would pin workerCount to 3 and skip calibration while delivering
* none of the benefit — e.g. a composition longer than
* `streamingEncodeMaxDurationSeconds` (240 s default), where the duration
* cap disables streaming before the router's force flag is consulted.
*/
parallelStreamingAvailable: boolean;
/** Machine RAM (os.totalmem, MB). */
totalMemoryMb: number;
/** RAM floor for routing; <=0 disables the guard. */
@@ -1338,6 +1348,7 @@ export function shouldPreferParallelDrawElement(args: {
}): boolean {
return (
args.routerEnabled &&
args.parallelStreamingAvailable &&
args.workerCount > 1 &&
typeof args.requestedWorkers !== "number" &&
args.useDrawElement &&
@@ -2366,6 +2377,15 @@ async function executeRenderPipeline(input: {
process.env.PRODUCER_EXPERIMENTAL_FAST_CAPTURE === "true" ||
process.env.HF_DE_PARALLEL_STREAM === "true",
routerEnabled: deParallelRouterEnabled,
// Router pins 3 workers for the streaming path; don't pin when the
// duration cap (or any other streaming gate) would turn that path off.
parallelStreamingAvailable: shouldUseStreamingEncode(
cfg,
outputFormat,
3,
job.duration,
true,
),
totalMemoryMb: Math.round(totalmem() / (1024 * 1024)),
minMemoryMb: deParallelMinMemoryMb,
});