97 lines
2.7 KiB
JavaScript
97 lines
2.7 KiB
JavaScript
/**
|
||
* 构建时根据可用内存 / CPU 计算 heap 与 webpack.parallelism。
|
||
* 优先读取 cgroup 上限(Docker / K8s),避免误用宿主机总内存。
|
||
*
|
||
* 可手动覆盖:NAVSPHERE_HEAP_MB、NAVSPHERE_WEBPACK_PARALLELISM
|
||
*/
|
||
const os = require("os");
|
||
const fs = require("fs");
|
||
|
||
function readCgroupMemoryLimitBytes() {
|
||
try {
|
||
const v2 = "/sys/fs/cgroup/memory.max";
|
||
if (fs.existsSync(v2)) {
|
||
const s = fs.readFileSync(v2, "utf8").trim();
|
||
if (s && s !== "max") {
|
||
const n = parseInt(s, 10);
|
||
if (n > 0 && n < 1e15) return n;
|
||
}
|
||
}
|
||
const v1 = "/sys/fs/cgroup/memory/memory.limit_in_bytes";
|
||
if (fs.existsSync(v1)) {
|
||
const n = parseInt(fs.readFileSync(v1, "utf8"), 10);
|
||
const host = os.totalmem();
|
||
if (n > 0 && n < 1e15 && n <= host * 4) return n;
|
||
}
|
||
} catch {
|
||
/* ignore */
|
||
}
|
||
return null;
|
||
}
|
||
|
||
function effectiveTotalBytes() {
|
||
const cgroup = readCgroupMemoryLimitBytes();
|
||
const host = os.totalmem();
|
||
if (cgroup == null) return host;
|
||
return Math.min(cgroup, host);
|
||
}
|
||
|
||
function parsePositiveInt(name) {
|
||
const v = process.env[name];
|
||
if (v == null || v === "") return null;
|
||
const n = parseInt(v, 10);
|
||
return Number.isFinite(n) && n > 0 ? n : null;
|
||
}
|
||
|
||
function getBuildProfile() {
|
||
const total = effectiveTotalBytes();
|
||
const memMB = total / 1024 / 1024;
|
||
const cpus =
|
||
typeof os.availableParallelism === "function"
|
||
? os.availableParallelism()
|
||
: os.cpus().length;
|
||
|
||
const heapOverride = parsePositiveInt("NAVSPHERE_HEAP_MB");
|
||
const parOverride = parsePositiveInt("NAVSPHERE_WEBPACK_PARALLELISM");
|
||
|
||
// V8 堆:取「比例」与「为系统预留」二者中较小者,避免占满整机触发 OOM killer
|
||
const byRatio = memMB * 0.32;
|
||
const reserveMB = memMB < 1024 ? 180 : 220;
|
||
const byHeadroom = Math.max(0, memMB - reserveMB);
|
||
let heapMB = Math.floor(Math.min(byRatio, byHeadroom));
|
||
heapMB = Math.min(4096, Math.max(384, heapMB));
|
||
|
||
if (heapOverride != null) {
|
||
heapMB = Math.min(8192, heapOverride);
|
||
}
|
||
|
||
// Webpack:内存或 CPU 偏低时保持 1;资源充足时适度提高(仍限制上限)
|
||
let parallelism = 1;
|
||
if (parOverride != null) {
|
||
parallelism = Math.min(8, parOverride);
|
||
} else {
|
||
if (memMB >= 1536 && cpus >= 2) {
|
||
parallelism = Math.min(4, Math.max(1, Math.floor(cpus / 2)));
|
||
}
|
||
if (memMB >= 4096 && cpus >= 4) {
|
||
parallelism = Math.min(6, Math.max(1, Math.floor(cpus * 0.75)));
|
||
}
|
||
if (memMB < 1200) {
|
||
parallelism = 1;
|
||
}
|
||
}
|
||
|
||
return {
|
||
heapMB,
|
||
parallelism,
|
||
totalBytes: total,
|
||
cpus,
|
||
memMB: Math.round(memMB * 10) / 10,
|
||
};
|
||
}
|
||
|
||
module.exports = {
|
||
getBuildProfile,
|
||
effectiveTotalBytes,
|
||
};
|