fix(engine): preserve Windows RSS samples after a query failure (#5357)

This commit is contained in:
Abdullah M. Nazif
2026-10-24 04:10:28 +00:00
committed by GitHub
parent cad57bf2aa
commit ba5dde78de
3 changed files with 45 additions and 2 deletions
@@ -1,4 +1,5 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { sampleProcessRss } from "../utils/processRss.js";
import {
createChromeMemorySampler,
mergeSample,
@@ -170,6 +171,31 @@ describe("createChromeMemorySampler", () => {
expect(sampler.stats()).toEqual(empty);
});
it("reports Windows browser and GPU memory when the renderer query fails", async () => {
const exec = async (_file: string, args: readonly string[]) => {
const pid = Number(args[4]?.slice("PID eq ".length));
if (pid === 2) throw new Error("tasklist timed out");
return { stdout: `"chrome.exe","${pid}","Console","1","${pid * 10240} K"\r\n` };
};
const onSample = vi.fn();
const sampler = createChromeMemorySampler({
getPids: async () => ({ browser: 1, renderers: [2], gpu: [3] }),
sampleRss: (pids) => sampleProcessRss(pids, exec, "win32"),
intervalMs: 100,
onSample,
});
await sampler.sampleOnce();
expect(sampler.stats()).toEqual({
browserRssPeakMb: 10,
rendererRssPeakMb: undefined,
rssLastMb: 40,
gpuProcessSeenLastSample: true,
samples: 1,
});
expect(onSample).toHaveBeenCalledWith(sampler.stats());
});
it("unrefs the interval so a forgotten stop() cannot hold the process open", () => {
// Real timers: a real NodeJS.Timeout reports hasRef(); the interval is far
// enough out that no tick fires during the test.
@@ -115,6 +115,21 @@ describe("sampleProcessRss", () => {
expect(result).toEqual([{ pid: 9, rssMb: 2 }]);
});
it.each([1, 2, 3])("keeps successful Windows samples when pid %i fails", async (failedPid) => {
const calls: number[] = [];
const exec = async (_file: string, args: readonly string[]) => {
const pid = Number(args[4]?.slice("PID eq ".length));
calls.push(pid);
if (pid === failedPid) throw new Error("tasklist timed out");
return { stdout: `"chrome.exe","${pid}","Console","1","${pid * 1024} K"\r\n` };
};
expect(await sampleProcessRss([1, 2, 3], exec, "win32")).toEqual(
[1, 2, 3].filter((pid) => pid !== failedPid).map((pid) => ({ pid, rssMb: pid })),
);
expect(calls).toEqual([1, 2, 3]);
});
it("drops invalid pids and duplicates before calling ps", async () => {
const calls: Array<readonly string[]> = [];
const exec = async (_file: string, args: readonly string[]) => {
+4 -2
View File
@@ -91,8 +91,10 @@ export async function sampleProcessRss(
if (platform === "win32") {
const results: ProcessRssSample[] = [];
for (const pid of unique) {
const { stdout } = await exec("tasklist", ["/FO", "CSV", "/NH", "/FI", `PID eq ${pid}`]);
results.push(...parseTasklistCsv(pid, stdout));
try {
const { stdout } = await exec("tasklist", ["/FO", "CSV", "/NH", "/FI", `PID eq ${pid}`]);
results.push(...parseTasklistCsv(pid, stdout));
} catch {}
}
return results;
}