process.cpuUsage()
上有NodeJS
函数和Deno.memoryUsage()
函数可以获取Deno
上的内存使用情况
还有 Deno 的流程模块,位于 https://deno.land/[email protected]/node/process.ts 但它不包括类似
.cpuUsage()
的内容
那么有没有办法获取当前的CPU使用率
Deno
?
在我写这个答案时,在 Deno 中本身不可能获取采样的 CPU 负载数据。
如果您现在想要此数据,可以通过以下两种方式之一获取:
我将在下面提供一个代码示例,介绍如何通过安装 Node.js 并使用第二种方法来获取数据:
node_eval.ts
:
type MaybePromise<T> = T | Promise<T>;
type Decodable = Parameters<TextDecoder['decode']>[0];
const decoder = new TextDecoder();
async function trimDecodable (decodable: MaybePromise<Decodable>): Promise<string> {
return decoder.decode(await decodable).trim();
}
/**
* Evaluates the provided script using Node.js (like
* [`eval`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval))
* and returns `stdout`.
*
* Uses the resolved version of `node` according to the host environemnt.
*
* Requires `node` to be available in `$PATH`.
* Requires permission `--allow-run=node`.
*/
export async function evaluateUsingNodeJS (script: string): Promise<string> {
const cmd = ['node', '-e', script];
const proc = Deno.run({cmd, stderr: 'piped', stdout: 'piped'});
const [{code}, stderr, stdout] = await Promise.all([
proc.status(),
trimDecodable(proc.stderrOutput()),
trimDecodable(proc.output()),
]);
if (code !== 0) {
const msg = stderr ? `\n${stderr}` : '';
throw new Error(`The "node" subprocess exited with a non-zero status code (${code}). If output was emitted to stderr, it is included below.${msg}`);
}
return stdout;
}
mod.ts
:
import {evaluateUsingNodeJS} from './node_eval.ts';
export const cpuTimesKeys: readonly (keyof CPUTimes)[] =
['user', 'nice', 'sys', 'idle', 'irq'];
export type CPUTimes = {
/** The number of milliseconds the CPU has spent in user mode */
user: number;
/**
* The number of milliseconds the CPU has spent in nice mode
*
* `nice` values are POSIX-only.
* On Windows, the nice values of all processors are always `0`.
*/
nice: number;
/** The number of milliseconds the CPU has spent in sys mode */
sys: number;
/** The number of milliseconds the CPU has spent in idle mode */
idle: number;
/** The number of milliseconds the CPU has spent in irq mode */
irq: number;
};
export type CPUCoreInfo = {
model: string;
/** in MHz */
speed: number;
times: CPUTimes;
};
/**
* Requires `node` to be available in `$PATH`.
* Requires permission `--allow-run=node`.
*/
export async function sampleCPUsUsingNodeJS (): Promise<CPUCoreInfo[]> {
const script = `console.log(JSON.stringify(require('os').cpus()));`;
const stdout = await evaluateUsingNodeJS(script);
try {
return JSON.parse(stdout) as CPUCoreInfo[];
}
catch (ex) {
const cause = ex instanceof Error ? ex : new Error(String(ex));
throw new Error(`The "node" subprocess output couldn't be parsed`, {cause});
}
}
/**
* (Same as `CPUCoreInfo`, but) aliased in recognition of the transfromation,
* in order to provide JSDoc info regarding the transformed type
*/
export type TransformedCoreInfo = Omit<CPUCoreInfo, 'times'> & {
/** Properties are decimal percentage of total time */
times: Record<keyof CPUCoreInfo['times'], number>;
};
/** Converts each time value (in ms) to a decimal percentage of their sum */
export function coreInfoAsPercentages (coreInfo: CPUCoreInfo): TransformedCoreInfo {
const timeEntries = Object.entries(coreInfo.times) as [
name: keyof CPUCoreInfo['times'],
ms: number,
][];
const sum = timeEntries.reduce((sum, [, ms]) => sum + ms, 0);
for (const [index, [, ms]] of timeEntries.entries()) {
timeEntries[index][1] = ms / sum;
}
const times = Object.fromEntries(timeEntries) as TransformedCoreInfo['times'];
return {...coreInfo, times};
}
example.ts
:
import {
coreInfoAsPercentages,
cpuTimesKeys,
sampleCPUsUsingNodeJS,
type CPUCoreInfo,
} from './mod.ts';
function anonymizeProcessorAttributes <T extends CPUCoreInfo>(coreInfoArray: T[]): T[] {
return coreInfoArray.map(info => ({
...info,
model: 'REDACTED',
speed: NaN,
}));
}
// Get the CPU info
const cpuCoreInfoArr = await sampleCPUsUsingNodeJS();
// Anonymizing my personal device details (but you would probably not use this)
const anonymized = anonymizeProcessorAttributes(cpuCoreInfoArr);
// JSON for log data
const jsonLogData = JSON.stringify(anonymized);
console.log(jsonLogData);
// Or, for purely visual inspection,
// round the percentages for greater scannability...
const roundedPercentages = anonymized.map(coreInfo => {
const asPercentages = coreInfoAsPercentages(coreInfo);
for (const key of cpuTimesKeys) {
asPercentages.times[key] = Math.round(asPercentages.times[key] * 100);
}
return asPercentages;
});
// and log in tabular format
console.table(roundedPercentages.map(({times}) => times));
在控制台中:
% deno run --allow-run=node example.ts
[{"model":"REDACTED","speed":null,"times":{"user":2890870,"nice":0,"sys":2290610,"idle":17913530,"irq":0}},{"model":"REDACTED","speed":null,"times":{"user":218270,"nice":0,"sys":188200,"idle":22687790,"irq":0}},{"model":"REDACTED","speed":null,"times":{"user":2509660,"nice":0,"sys":1473010,"idle":19111680,"irq":0}},{"model":"REDACTED","speed":null,"times":{"user":221630,"nice":0,"sys":174140,"idle":22698480,"irq":0}},{"model":"REDACTED","speed":null,"times":{"user":2161140,"nice":0,"sys":1086970,"idle":19846200,"irq":0}},{"model":"REDACTED","speed":null,"times":{"user":221800,"nice":0,"sys":157620,"idle":22714800,"irq":0}},{"model":"REDACTED","speed":null,"times":{"user":1905230,"nice":0,"sys":897140,"idle":20291910,"irq":0}},{"model":"REDACTED","speed":null,"times":{"user":224060,"nice":0,"sys":146460,"idle":22723700,"irq":0}}]
┌───────┬──────┬──────┬─────┬──────┬─────┐
│ (idx) │ user │ nice │ sys │ idle │ irq │
├───────┼──────┼──────┼─────┼──────┼─────┤
│ 0 │ 13 │ 0 │ 10 │ 78 │ 0 │
│ 1 │ 1 │ 0 │ 1 │ 98 │ 0 │
│ 2 │ 11 │ 0 │ 6 │ 83 │ 0 │
│ 3 │ 1 │ 0 │ 1 │ 98 │ 0 │
│ 4 │ 9 │ 0 │ 5 │ 86 │ 0 │
│ 5 │ 1 │ 0 │ 1 │ 98 │ 0 │
│ 6 │ 8 │ 0 │ 4 │ 88 │ 0 │
│ 7 │ 1 │ 0 │ 1 │ 98 │ 0 │
└───────┴──────┴──────┴─────┴──────┴─────┘
截至 2024 年,该功能运行良好(使用 Deno v1.45.2 进行测试):
import { cpus } from "node:os";
console.log(Deno.loadavg()[0] / cpus().length);
Deno.loadavg()
返回一个 3 元素数组 - 1 分钟、5 分钟、15 分钟的 CPU 使用率平均值,其中值 1 表示当前正在使用相当于 1 个完整逻辑 CPU 核心(即“线程”)。所以我们需要将它除以逻辑核心的数量,我们可以通过节点cpus
函数得到。