Skip to content

Commit c560a18

Browse files
committed
Make it easy to take NODE_OPTIONS and set the old space flag
1 parent 0ce5e0f commit c560a18

File tree

3 files changed

+104
-3
lines changed

3 files changed

+104
-3
lines changed

packages/core/src/v3/machines/index.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,50 @@ import { MachinePreset } from "../schemas/common.js";
88
* @param {number} [overhead=0.2] - The memory overhead factor (0.2 = 20% reserved for system operations)
99
* @returns {number} The calculated max old space size in MiB
1010
*/
11-
export function maxOldSpaceSizeForMachine(machine: MachinePreset, overhead = 0.2) {
12-
return machine.memory * 1_024 * (1 - overhead);
11+
export function maxOldSpaceSizeForMachine(machine: MachinePreset, overhead: number = 0.2): number {
12+
return Math.round(machine.memory * 1_024 * (1 - overhead));
13+
}
14+
15+
/**
16+
* Returns a flag to be used for `--max-old-space-size`. It is in MiB.
17+
* Setting this correctly means V8 spends more times running Garbage Collection (GC).
18+
* It won't eliminate crashes but it will help avoid them.
19+
* @param {MachinePreset} machine - The machine preset configuration containing memory specifications
20+
* @param {number} [overhead=0.2] - The memory overhead factor (0.2 = 20% reserved for system operations)
21+
* @returns {string} The calculated max old space size flag
22+
*/
23+
export function maxOldSpaceSizeFlag(machine: MachinePreset, overhead: number = 0.2): string {
24+
return `--max-old-space-size=${maxOldSpaceSizeForMachine(machine, overhead)}`;
25+
}
26+
27+
/**
28+
* Takes the existing NODE_OPTIONS value, removes any existing max-old-space-size flag, and adds a new one.
29+
* @param {string | undefined} existingOptions - The existing NODE_OPTIONS value
30+
* @param {MachinePreset} machine - The machine preset configuration containing memory specifications
31+
* @param {number} [overhead=0.2] - The memory overhead factor (0.2 = 20% reserved for system operations)
32+
* @returns {string} The updated NODE_OPTIONS value with the new max-old-space-size flag
33+
*/
34+
export function nodeOptionsWithMaxOldSpaceSize(
35+
existingOptions: string | undefined,
36+
machine: MachinePreset,
37+
overhead: number = 0.2
38+
): string {
39+
let options = existingOptions ?? "";
40+
41+
//remove existing max-old-space-size flag
42+
options = options.replace(/--max-old-space-size=\d+/g, "").trim();
43+
44+
//get max-old-space-size flag
45+
const flag = maxOldSpaceSizeFlag(machine, overhead);
46+
47+
return normalizeCommandLineFlags(options ? `${options} ${flag}` : flag);
48+
}
49+
50+
/**
51+
* Normalizes spaces in a string of command line flags, ensuring single spaces between flags
52+
* @param {string} input - The string to normalize
53+
* @returns {string} The normalized string with single spaces between flags
54+
*/
55+
function normalizeCommandLineFlags(input: string): string {
56+
return input.split(/\s+/).filter(Boolean).join(" ");
1357
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { describe, it, expect } from "vitest";
2+
import { nodeOptionsWithMaxOldSpaceSize } from "./index.js";
3+
import { MachinePreset } from "../schemas/common.js";
4+
5+
describe("nodeOptionsWithMaxOldSpaceSize", () => {
6+
const testMachine: MachinePreset = {
7+
name: "small-2x",
8+
memory: 1, // 1GB = 1024 MiB
9+
cpu: 1,
10+
centsPerMs: 0,
11+
};
12+
13+
// With default 0.2 overhead, max-old-space-size should be 819 (1024 * 0.8)
14+
const expectedFlag = "--max-old-space-size=819";
15+
16+
it("handles undefined NODE_OPTIONS", () => {
17+
const result = nodeOptionsWithMaxOldSpaceSize(undefined, testMachine);
18+
expect(result).toBe(expectedFlag);
19+
});
20+
21+
it("handles empty string NODE_OPTIONS", () => {
22+
const result = nodeOptionsWithMaxOldSpaceSize("", testMachine);
23+
expect(result).toBe(expectedFlag);
24+
});
25+
26+
it("preserves existing flags while adding max-old-space-size", () => {
27+
const result = nodeOptionsWithMaxOldSpaceSize("--inspect --trace-warnings", testMachine);
28+
expect(result).toBe(`--inspect --trace-warnings ${expectedFlag}`);
29+
});
30+
31+
it("replaces existing max-old-space-size flag", () => {
32+
const result = nodeOptionsWithMaxOldSpaceSize(
33+
"--max-old-space-size=4096 --inspect",
34+
testMachine
35+
);
36+
expect(result).toBe(`--inspect ${expectedFlag}`);
37+
});
38+
39+
it("handles multiple existing max-old-space-size flags", () => {
40+
const result = nodeOptionsWithMaxOldSpaceSize(
41+
"--max-old-space-size=4096 --inspect --max-old-space-size=8192",
42+
testMachine
43+
);
44+
expect(result).toBe(`--inspect ${expectedFlag}`);
45+
});
46+
47+
it("handles extra spaces between flags", () => {
48+
const result = nodeOptionsWithMaxOldSpaceSize("--inspect --trace-warnings", testMachine);
49+
expect(result).toBe(`--inspect --trace-warnings ${expectedFlag}`);
50+
});
51+
52+
it("uses custom overhead value", () => {
53+
const result = nodeOptionsWithMaxOldSpaceSize("--inspect", testMachine, 0.5);
54+
// With 0.5 overhead, max-old-space-size should be 512 (1024 * 0.5)
55+
expect(result).toBe("--inspect --max-old-space-size=512");
56+
});
57+
});

packages/core/vitest.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { defineConfig } from "vitest/config";
22

33
export default defineConfig({
44
test: {
5-
include: ["test/**/*.test.ts"],
5+
include: ["test/**/*.test.ts", "src/v3/**/*.test.ts"],
66
globals: true,
77
},
88
});

0 commit comments

Comments
 (0)