2022-02-05 11:14:19 +01:00

1682 lines
58 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
// @ts-check
// ==================================================================================
// cpu.js
// ----------------------------------------------------------------------------------
// Description: System Information - library
// for Node.js
// Copyright: (c) 2014 - 2022
// Author: Sebastian Hildebrandt
// ----------------------------------------------------------------------------------
// License: MIT
// ==================================================================================
// 4. CPU
// ----------------------------------------------------------------------------------
const os = require('os');
const exec = require('child_process').exec;
const execSync = require('child_process').execSync;
const fs = require('fs');
const util = require('./util');
let _platform = process.platform;
const _linux = (_platform === 'linux' || _platform === 'android');
const _darwin = (_platform === 'darwin');
const _windows = (_platform === 'win32');
const _freebsd = (_platform === 'freebsd');
const _openbsd = (_platform === 'openbsd');
const _netbsd = (_platform === 'netbsd');
const _sunos = (_platform === 'sunos');
let _cpu_speed = 0;
let _current_cpu = {
user: 0,
nice: 0,
system: 0,
idle: 0,
irq: 0,
load: 0,
tick: 0,
ms: 0,
currentLoad: 0,
currentLoadUser: 0,
currentLoadSystem: 0,
currentLoadNice: 0,
currentLoadIdle: 0,
currentLoadIrq: 0,
rawCurrentLoad: 0,
rawCurrentLoadUser: 0,
rawCurrentLoadSystem: 0,
rawCurrentLoadNice: 0,
rawCurrentLoadIdle: 0,
rawCurrentLoadIrq: 0
};
let _cpus = [];
let _corecount = 0;
const AMDBaseFrequencies = {
'8346': '1.8',
'8347': '1.9',
'8350': '2.0',
'8354': '2.2',
'8356|SE': '2.4',
'8356': '2.3',
'8360': '2.5',
'2372': '2.1',
'2373': '2.1',
'2374': '2.2',
'2376': '2.3',
'2377': '2.3',
'2378': '2.4',
'2379': '2.4',
'2380': '2.5',
'2381': '2.5',
'2382': '2.6',
'2384': '2.7',
'2386': '2.8',
'2387': '2.8',
'2389': '2.9',
'2393': '3.1',
'8374': '2.2',
'8376': '2.3',
'8378': '2.4',
'8379': '2.4',
'8380': '2.5',
'8381': '2.5',
'8382': '2.6',
'8384': '2.7',
'8386': '2.8',
'8387': '2.8',
'8389': '2.9',
'8393': '3.1',
'2419EE': '1.8',
'2423HE': '2.0',
'2425HE': '2.1',
'2427': '2.2',
'2431': '2.4',
'2435': '2.6',
'2439SE': '2.8',
'8425HE': '2.1',
'8431': '2.4',
'8435': '2.6',
'8439SE': '2.8',
'4122': '2.2',
'4130': '2.6',
'4162EE': '1.7',
'4164EE': '1.8',
'4170HE': '2.1',
'4174HE': '2.3',
'4176HE': '2.4',
'4180': '2.6',
'4184': '2.8',
'6124HE': '1.8',
'6128HE': '2.0',
'6132HE': '2.2',
'6128': '2.0',
'6134': '2.3',
'6136': '2.4',
'6140': '2.6',
'6164HE': '1.7',
'6166HE': '1.8',
'6168': '1.9',
'6172': '2.1',
'6174': '2.2',
'6176': '2.3',
'6176SE': '2.3',
'6180SE': '2.5',
'3250': '2.5',
'3260': '2.7',
'3280': '2.4',
'4226': '2.7',
'4228': '2.8',
'4230': '2.9',
'4234': '3.1',
'4238': '3.3',
'4240': '3.4',
'4256': '1.6',
'4274': '2.5',
'4276': '2.6',
'4280': '2.8',
'4284': '3.0',
'6204': '3.3',
'6212': '2.6',
'6220': '3.0',
'6234': '2.4',
'6238': '2.6',
'6262HE': '1.6',
'6272': '2.1',
'6274': '2.2',
'6276': '2.3',
'6278': '2.4',
'6282SE': '2.6',
'6284SE': '2.7',
'6308': '3.5',
'6320': '2.8',
'6328': '3.2',
'6338P': '2.3',
'6344': '2.6',
'6348': '2.8',
'6366': '1.8',
'6370P': '2.0',
'6376': '2.3',
'6378': '2.4',
'6380': '2.5',
'6386': '2.8',
'FX|4100': '3.6',
'FX|4120': '3.9',
'FX|4130': '3.8',
'FX|4150': '3.8',
'FX|4170': '4.2',
'FX|6100': '3.3',
'FX|6120': '3.6',
'FX|6130': '3.6',
'FX|6200': '3.8',
'FX|8100': '2.8',
'FX|8120': '3.1',
'FX|8140': '3.2',
'FX|8150': '3.6',
'FX|8170': '3.9',
'FX|4300': '3.8',
'FX|4320': '4.0',
'FX|4350': '4.2',
'FX|6300': '3.5',
'FX|6350': '3.9',
'FX|8300': '3.3',
'FX|8310': '3.4',
'FX|8320': '3.5',
'FX|8350': '4.0',
'FX|8370': '4.0',
'FX|9370': '4.4',
'FX|9590': '4.7',
'FX|8320E': '3.2',
'FX|8370E': '3.3',
// ZEN Desktop CPUs
'1200': '3.1',
'Pro 1200': '3.1',
'1300X': '3.5',
'Pro 1300': '3.5',
'1400': '3.2',
'1500X': '3.5',
'Pro 1500': '3.5',
'1600': '3.2',
'1600X': '3.6',
'Pro 1600': '3.2',
'1700': '3.0',
'Pro 1700': '3.0',
'1700X': '3.4',
'Pro 1700X': '3.4',
'1800X': '3.6',
'1900X': '3.8',
'1920': '3.2',
'1920X': '3.5',
'1950X': '3.4',
// ZEN Desktop APUs
'200GE': '3.2',
'Pro 200GE': '3.2',
'220GE': '3.4',
'240GE': '3.5',
'3000G': '3.5',
'300GE': '3.4',
'3050GE': '3.4',
'2200G': '3.5',
'Pro 2200G': '3.5',
'2200GE': '3.2',
'Pro 2200GE': '3.2',
'2400G': '3.6',
'Pro 2400G': '3.6',
'2400GE': '3.2',
'Pro 2400GE': '3.2',
// ZEN Mobile APUs
'Pro 200U': '2.3',
'300U': '2.4',
'2200U': '2.5',
'3200U': '2.6',
'2300U': '2.0',
'Pro 2300U': '2.0',
'2500U': '2.0',
'Pro 2500U': '2.2',
'2600H': '3.2',
'2700U': '2.0',
'Pro 2700U': '2.2',
'2800H': '3.3',
// ZEN Server Processors
'7351': '2.4',
'7351P': '2.4',
'7401': '2.0',
'7401P': '2.0',
'7551P': '2.0',
'7551': '2.0',
'7251': '2.1',
'7261': '2.5',
'7281': '2.1',
'7301': '2.2',
'7371': '3.1',
'7451': '2.3',
'7501': '2.0',
'7571': '2.2',
'7601': '2.2',
// ZEN Embedded Processors
'V1500B': '2.2',
'V1780B': '3.35',
'V1202B': '2.3',
'V1404I': '2.0',
'V1605B': '2.0',
'V1756B': '3.25',
'V1807B': '3.35',
'3101': '2.1',
'3151': '2.7',
'3201': '1.5',
'3251': '2.5',
'3255': '2.5',
'3301': '2.0',
'3351': '1.9',
'3401': '1.85',
'3451': '2.15',
// ZEN+ Desktop
'1200|AF': '3.1',
'2300X': '3.5',
'2500X': '3.6',
'2600': '3.4',
'2600E': '3.1',
'1600|AF': '3.2',
'2600X': '3.6',
'2700': '3.2',
'2700E': '2.8',
'Pro 2700': '3.2',
'2700X': '3.7',
'Pro 2700X': '3.6',
'2920X': '3.5',
'2950X': '3.5',
'2970WX': '3.0',
'2990WX': '3.0',
// ZEN+ Desktop APU
'Pro 300GE': '3.4',
'Pro 3125GE': '3.4',
'3150G': '3.5',
'Pro 3150G': '3.5',
'3150GE': '3.3',
'Pro 3150GE': '3.3',
'3200G': '3.6',
'Pro 3200G': '3.6',
'3200GE': '3.3',
'Pro 3200GE': '3.3',
'3350G': '3.6',
'Pro 3350G': '3.6',
'3350GE': '3.3',
'Pro 3350GE': '3.3',
'3400G': '3.7',
'Pro 3400G': '3.7',
'3400GE': '3.3',
'Pro 3400GE': '3.3',
// ZEN+ Mobile
'3300U': '2.1',
'PRO 3300U': '2.1',
'3450U': '2.1',
'3500U': '2.1',
'PRO 3500U': '2.1',
'3500C': '2.1',
'3550H': '2.1',
'3580U': '2.1',
'3700U': '2.3',
'PRO 3700U': '2.3',
'3700C': '2.3',
'3750H': '2.3',
'3780U': '2.3',
// ZEN2 Desktop CPUS
'3100': '3.6',
'3300X': '3.8',
'3500': '3.6',
'3500X': '3.6',
'3600': '3.6',
'Pro 3600': '3.6',
'3600X': '3.8',
'3600XT': '3.8',
'Pro 3700': '3.6',
'3700X': '3.6',
'3800X': '3.9',
'3800XT': '3.9',
'3900': '3.1',
'Pro 3900': '3.1',
'3900X': '3.8',
'3900XT': '3.8',
'3950X': '3.5',
'3960X': '3.8',
'3970X': '3.7',
'3990X': '2.9',
'3945WX': '4.0',
'3955WX': '3.9',
'3975WX': '3.5',
'3995WX': '2.7',
// ZEN2 Desktop APUs
'4300GE': '3.5',
'Pro 4300GE': '3.5',
'4300G': '3.8',
'Pro 4300G': '3.8',
'4600GE': '3.3',
'Pro 4650GE': '3.3',
'4600G': '3.7',
'Pro 4650G': '3.7',
'4700GE': '3.1',
'Pro 4750GE': '3.1',
'4700G': '3.6',
'Pro 4750G': '3.6',
'4300U': '2.7',
'4450U': '2.5',
'Pro 4450U': '2.5',
'4500U': '2.3',
'4600U': '2.1',
'PRO 4650U': '2.1',
'4680U': '2.1',
'4600HS': '3.0',
'4600H': '3.0',
'4700U': '2.0',
'PRO 4750U': '1.7',
'4800U': '1.8',
'4800HS': '2.9',
'4800H': '2.9',
'4900HS': '3.0',
'4900H': '3.3',
'5300U': '2.6',
'5500U': '2.1',
'5700U': '1.8',
// ZEN2 - EPYC
'7232P': '3.1',
'7302P': '3.0',
'7402P': '2.8',
'7502P': '2.5',
'7702P': '2.0',
'7252': '3.1',
'7262': '3.2',
'7272': '2.9',
'7282': '2.8',
'7302': '3.0',
'7352': '2.3',
'7402': '2.8',
'7452': '2.35',
'7502': '2.5',
'7532': '2.4',
'7542': '2.9',
'7552': '2.2',
'7642': '2.3',
'7662': '2.0',
'7702': '2.0',
'7742': '2.25',
'7H12': '2.6',
'7F32': '3.7',
'7F52': '3.5',
'7F72': '3.2',
// Epyc (Milan)
'7763': '2.45',
'7713': '2.0',
'7713P': '2.0',
'7663': '2.0',
'7643': '2.3',
'75F3': '2.95',
'7543': '2.8',
'7543P': '2.8',
'7513': '2.6',
'7453': '2.75',
'74F3': '3.2',
'7443': '2.85',
'7443P': '2.85',
'7413': '2.65',
'73F3': '3.5',
'7343': '3.2',
'7313': '3.0',
'7313P': '3.0',
'72F3': '3.7',
// ZEN3
'5600X': '3.7',
'5800X': '3.8',
'5900X': '3.7',
'5950X': '3.4'
};
const socketTypes = {
1: 'Other',
2: 'Unknown',
3: 'Daughter Board',
4: 'ZIF Socket',
5: 'Replacement/Piggy Back',
6: 'None',
7: 'LIF Socket',
8: 'Slot 1',
9: 'Slot 2',
10: '370 Pin Socket',
11: 'Slot A',
12: 'Slot M',
13: '423',
14: 'A (Socket 462)',
15: '478',
16: '754',
17: '940',
18: '939',
19: 'mPGA604',
20: 'LGA771',
21: 'LGA775',
22: 'S1',
23: 'AM2',
24: 'F (1207)',
25: 'LGA1366',
26: 'G34',
27: 'AM3',
28: 'C32',
29: 'LGA1156',
30: 'LGA1567',
31: 'PGA988A',
32: 'BGA1288',
33: 'rPGA988B',
34: 'BGA1023',
35: 'BGA1224',
36: 'LGA1155',
37: 'LGA1356',
38: 'LGA2011',
39: 'FS1',
40: 'FS2',
41: 'FM1',
42: 'FM2',
43: 'LGA2011-3',
44: 'LGA1356-3',
45: 'LGA1150',
46: 'BGA1168',
47: 'BGA1234',
48: 'BGA1364',
49: 'AM4',
50: 'LGA1151',
51: 'BGA1356',
52: 'BGA1440',
53: 'BGA1515',
54: 'LGA3647-1',
55: 'SP3',
56: 'SP3r2',
57: 'LGA2066',
58: 'BGA1392',
59: 'BGA1510',
60: 'BGA1528',
61: 'LGA4189',
62: 'LGA1200',
63: 'LGA4677',
};
function cpuManufacturer(str) {
let result = str;
str = str.toLowerCase();
if (str.indexOf('intel') >= 0) { result = 'Intel'; }
if (str.indexOf('amd') >= 0) { result = 'AMD'; }
if (str.indexOf('qemu') >= 0) { result = 'QEMU'; }
if (str.indexOf('hygon') >= 0) { result = 'Hygon'; }
if (str.indexOf('centaur') >= 0) { result = 'WinChip/Via'; }
if (str.indexOf('vmware') >= 0) { result = 'VMware'; }
if (str.indexOf('Xen') >= 0) { result = 'Xen Hypervisor'; }
if (str.indexOf('tcg') >= 0) { result = 'QEMU'; }
if (str.indexOf('apple') >= 0) { result = 'Apple'; }
return result;
}
function cpuBrandManufacturer(res) {
res.brand = res.brand.replace(/\(R\)+/g, '®').replace(/\s+/g, ' ').trim();
res.brand = res.brand.replace(/\(TM\)+/g, '™').replace(/\s+/g, ' ').trim();
res.brand = res.brand.replace(/\(C\)+/g, '©').replace(/\s+/g, ' ').trim();
res.brand = res.brand.replace(/CPU+/g, '').replace(/\s+/g, ' ').trim();
res.manufacturer = cpuManufacturer(res.brand);
let parts = res.brand.split(' ');
parts.shift();
res.brand = parts.join(' ');
return res;
}
function getAMDSpeed(brand) {
let result = '0';
for (let key in AMDBaseFrequencies) {
if ({}.hasOwnProperty.call(AMDBaseFrequencies, key)) {
let parts = key.split('|');
let found = 0;
parts.forEach(item => {
if (brand.indexOf(item) > -1) {
found++;
}
});
if (found === parts.length) {
result = AMDBaseFrequencies[key];
}
}
}
return parseFloat(result);
}
// --------------------------
// CPU - brand, speed
function getCpu() {
return new Promise((resolve) => {
process.nextTick(() => {
const UNKNOWN = 'unknown';
let result = {
manufacturer: UNKNOWN,
brand: UNKNOWN,
vendor: '',
family: '',
model: '',
stepping: '',
revision: '',
voltage: '',
speed: 0,
speedMin: 0,
speedMax: 0,
governor: '',
cores: util.cores(),
physicalCores: util.cores(),
processors: 1,
socket: '',
flags: '',
virtualization: false,
cache: {}
};
cpuFlags().then(flags => {
result.flags = flags;
result.virtualization = flags.indexOf('vmx') > -1 || flags.indexOf('svm') > -1;
// if (_windows) {
// try {
// const systeminfo = execSync('systeminfo', util.execOptsWin).toString();
// result.virtualization = result.virtualization || (systeminfo.indexOf('Virtualization Enabled In Firmware: Yes') !== -1) || (systeminfo.indexOf('Virtualisierung in Firmware aktiviert: Ja') !== -1) || (systeminfo.indexOf('Virtualisation activée dans le microprogramme : Qiu') !== -1);
// } catch (e) {
// util.noop();
// }
// }
if (_darwin) {
exec('sysctl machdep.cpu hw.cpufrequency_max hw.cpufrequency_min hw.packages hw.physicalcpu_max hw.ncpu hw.tbfrequency hw.cpufamily hw.cpusubfamily', function (error, stdout) {
let lines = stdout.toString().split('\n');
const modelline = util.getValue(lines, 'machdep.cpu.brand_string');
const modellineParts = modelline.split('@');
result.brand = modellineParts[0].trim();
const speed = modellineParts[1] ? modellineParts[1].trim() : '0';
result.speed = parseFloat(speed.replace(/GHz+/g, ''));
let tbFrequency = util.getValue(lines, 'hw.tbfrequency') / 1000000000.0;
tbFrequency = tbFrequency < 0.1 ? tbFrequency * 100 : tbFrequency;
result.speed = result.speed === 0 ? tbFrequency : result.speed;
_cpu_speed = result.speed;
result = cpuBrandManufacturer(result);
result.speedMin = util.getValue(lines, 'hw.cpufrequency_min') ? (util.getValue(lines, 'hw.cpufrequency_min') / 1000000000.0) : result.speed;
result.speedMax = util.getValue(lines, 'hw.cpufrequency_max') ? (util.getValue(lines, 'hw.cpufrequency_max') / 1000000000.0) : result.speed;
result.vendor = util.getValue(lines, 'machdep.cpu.vendor') || 'Apple';
result.family = util.getValue(lines, 'machdep.cpu.family') || util.getValue(lines, 'hw.cpufamily');
result.model = util.getValue(lines, 'machdep.cpu.model');
result.stepping = util.getValue(lines, 'machdep.cpu.stepping') || util.getValue(lines, 'hw.cpusubfamily');
const countProcessors = util.getValue(lines, 'hw.packages');
const countCores = util.getValue(lines, 'hw.physicalcpu_max');
const countThreads = util.getValue(lines, 'hw.ncpu');
if (os.arch() === 'arm64') {
const clusters = execSync('ioreg -c IOPlatformDevice -d 3 -r | grep cluster-type').toString().split('\n');
const efficiencyCores = clusters.filter(line => line.indexOf('"E"') >= 0).length;
const performanceCores = clusters.filter(line => line.indexOf('"P"') >= 0).length;
result.socket = 'SOC';
result.efficiencyCores = efficiencyCores;
result.performanceCores = performanceCores;
}
if (countProcessors) {
result.processors = parseInt(countProcessors) || 1;
}
if (countCores && countThreads) {
result.cores = parseInt(countThreads) || util.cores();
result.physicalCores = parseInt(countCores) || util.cores();
}
cpuCache().then(res => {
result.cache = res;
resolve(result);
});
});
}
if (_linux) {
let modelline = '';
let lines = [];
if (os.cpus()[0] && os.cpus()[0].model) { modelline = os.cpus()[0].model; }
exec('export LC_ALL=C; lscpu; echo -n "Governor: "; cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null; echo; unset LC_ALL', function (error, stdout) {
if (!error) {
lines = stdout.toString().split('\n');
}
modelline = util.getValue(lines, 'model name') || modelline;
const modellineParts = modelline.split('@');
result.brand = modellineParts[0].trim();
result.speed = modellineParts[1] ? parseFloat(modellineParts[1].trim()) : 0;
if (result.speed === 0 && (result.brand.indexOf('AMD') > -1 || result.brand.toLowerCase().indexOf('ryzen') > -1)) {
result.speed = getAMDSpeed(result.brand);
}
if (result.speed === 0) {
const current = getCpuCurrentSpeedSync();
if (current.avg !== 0) { result.speed = current.avg; }
}
_cpu_speed = result.speed;
result.speedMin = Math.round(parseFloat(util.getValue(lines, 'cpu min mhz').replace(/,/g, '.')) / 10.0) / 100;
result.speedMax = Math.round(parseFloat(util.getValue(lines, 'cpu max mhz').replace(/,/g, '.')) / 10.0) / 100;
result = cpuBrandManufacturer(result);
result.vendor = cpuManufacturer(util.getValue(lines, 'vendor id'));
// if (!result.vendor) { result.vendor = util.getValue(lines, 'anbieterkennung'); }
result.family = util.getValue(lines, 'cpu family');
// if (!result.family) { result.family = util.getValue(lines, 'prozessorfamilie'); }
result.model = util.getValue(lines, 'model:');
// if (!result.model) { result.model = util.getValue(lines, 'modell:'); }
result.stepping = util.getValue(lines, 'stepping');
result.revision = util.getValue(lines, 'cpu revision');
result.cache.l1d = util.getValue(lines, 'l1d cache');
if (result.cache.l1d) { result.cache.l1d = parseInt(result.cache.l1d) * (result.cache.l1d.indexOf('M') !== -1 ? 1024 * 1024 : (result.cache.l1d.indexOf('K') !== -1 ? 1024 : 1)); }
result.cache.l1i = util.getValue(lines, 'l1i cache');
if (result.cache.l1i) { result.cache.l1i = parseInt(result.cache.l1i) * (result.cache.l1i.indexOf('M') !== -1 ? 1024 * 1024 : (result.cache.l1i.indexOf('K') !== -1 ? 1024 : 1)); }
result.cache.l2 = util.getValue(lines, 'l2 cache');
if (result.cache.l2) { result.cache.l2 = parseInt(result.cache.l2) * (result.cache.l2.indexOf('M') !== -1 ? 1024 * 1024 : (result.cache.l2.indexOf('K') !== -1 ? 1024 : 1)); }
result.cache.l3 = util.getValue(lines, 'l3 cache');
if (result.cache.l3) { result.cache.l3 = parseInt(result.cache.l3) * (result.cache.l3.indexOf('M') !== -1 ? 1024 * 1024 : (result.cache.l3.indexOf('K') !== -1 ? 1024 : 1)); }
const threadsPerCore = util.getValue(lines, 'thread(s) per core') || '1';
// const coresPerSocketInt = parseInt(util.getValue(lines, 'cores(s) per socket') || '1', 10);
const processors = util.getValue(lines, 'socket(s)') || '1';
let threadsPerCoreInt = parseInt(threadsPerCore, 10);
let processorsInt = parseInt(processors, 10);
result.physicalCores = result.cores / threadsPerCoreInt;
result.processors = processorsInt;
result.governor = util.getValue(lines, 'governor') || '';
// Test Raspberry
if (result.vendor === 'ARM') {
const linesRpi = fs.readFileSync('/proc/cpuinfo').toString().split('\n');
const rPIRevision = util.decodePiCpuinfo(linesRpi);
if (rPIRevision.model.toLowerCase().indexOf('raspberry') >= 0) {
result.family = result.manufacturer;
result.manufacturer = rPIRevision.manufacturer;
result.brand = rPIRevision.processor;
result.revision = rPIRevision.revisionCode;
result.socket = 'SOC';
}
}
// socket type
let lines2 = [];
exec('export LC_ALL=C; dmidecode t 4 2>/dev/null | grep "Upgrade: Socket"; unset LC_ALL', function (error2, stdout2) {
lines2 = stdout2.toString().split('\n');
if (lines2 && lines2.length) {
result.socket = util.getValue(lines2, 'Upgrade').replace('Socket', '').trim() || result.socket;
}
resolve(result);
});
});
}
if (_freebsd || _openbsd || _netbsd) {
let modelline = '';
let lines = [];
if (os.cpus()[0] && os.cpus()[0].model) { modelline = os.cpus()[0].model; }
exec('export LC_ALL=C; dmidecode -t 4; dmidecode -t 7 unset LC_ALL', function (error, stdout) {
let cache = [];
if (!error) {
const data = stdout.toString().split('# dmidecode');
const processor = data.length > 1 ? data[1] : '';
cache = data.length > 2 ? data[2].split('Cache Information') : [];
lines = processor.split('\n');
}
result.brand = modelline.split('@')[0].trim();
result.speed = modelline.split('@')[1] ? parseFloat(modelline.split('@')[1].trim()) : 0;
if (result.speed === 0 && (result.brand.indexOf('AMD') > -1 || result.brand.toLowerCase().indexOf('ryzen') > -1)) {
result.speed = getAMDSpeed(result.brand);
}
if (result.speed === 0) {
const current = getCpuCurrentSpeedSync();
if (current.avg !== 0) { result.speed = current.avg; }
}
_cpu_speed = result.speed;
result.speedMin = result.speed;
result.speedMax = Math.round(parseFloat(util.getValue(lines, 'max speed').replace(/Mhz/g, '')) / 10.0) / 100;
result = cpuBrandManufacturer(result);
result.vendor = cpuManufacturer(util.getValue(lines, 'manufacturer'));
let sig = util.getValue(lines, 'signature');
sig = sig.split(',');
for (var i = 0; i < sig.length; i++) {
sig[i] = sig[i].trim();
}
result.family = util.getValue(sig, 'Family', ' ', true);
result.model = util.getValue(sig, 'Model', ' ', true);
result.stepping = util.getValue(sig, 'Stepping', ' ', true);
result.revision = '';
const voltage = parseFloat(util.getValue(lines, 'voltage'));
result.voltage = isNaN(voltage) ? '' : voltage.toFixed(2);
for (let i = 0; i < cache.length; i++) {
lines = cache[i].split('\n');
let cacheType = util.getValue(lines, 'Socket Designation').toLowerCase().replace(' ', '-').split('-');
cacheType = cacheType.length ? cacheType[0] : '';
const sizeParts = util.getValue(lines, 'Installed Size').split(' ');
let size = parseInt(sizeParts[0], 10);
const unit = sizeParts.length > 1 ? sizeParts[1] : 'kb';
size = size * (unit === 'kb' ? 1024 : (unit === 'mb' ? 1024 * 1024 : (unit === 'gb' ? 1024 * 1024 * 1024 : 1)));
if (cacheType) {
if (cacheType === 'l1') {
result.cache[cacheType + 'd'] = size / 2;
result.cache[cacheType + 'i'] = size / 2;
} else {
result.cache[cacheType] = size;
}
}
}
// socket type
result.socket = util.getValue(lines, 'Upgrade').replace('Socket', '').trim();
// # threads / # cores
const threadCount = util.getValue(lines, 'thread count').trim();
const coreCount = util.getValue(lines, 'core count').trim();
if (coreCount && threadCount) {
result.cores = parseInt(threadCount, 10);
result.physicalCores = parseInt(coreCount, 10);
}
resolve(result);
});
}
if (_sunos) {
resolve(result);
}
if (_windows) {
try {
const workload = [];
workload.push(util.powerShell('Get-WmiObject Win32_processor | select Name, Revision, L2CacheSize, L3CacheSize, Manufacturer, MaxClockSpeed, Description, UpgradeMethod, Caption, NumberOfLogicalProcessors, NumberOfCores | fl'));
workload.push(util.powerShell('Get-WmiObject Win32_CacheMemory | select CacheType,InstalledSize,Level | fl'));
// workload.push(util.powerShell('Get-ComputerInfo -property "HyperV*"'));
workload.push(util.powerShell('(Get-CimInstance Win32_ComputerSystem).HypervisorPresent'));
Promise.all(
workload
).then(data => {
let lines = data[0].split('\r\n');
let name = util.getValue(lines, 'name', ':') || '';
if (name.indexOf('@') >= 0) {
result.brand = name.split('@')[0].trim();
result.speed = name.split('@')[1] ? parseFloat(name.split('@')[1].trim()) : 0;
_cpu_speed = result.speed;
} else {
result.brand = name.trim();
result.speed = 0;
}
result = cpuBrandManufacturer(result);
result.revision = util.getValue(lines, 'revision', ':');
result.cache.l1d = 0;
result.cache.l1i = 0;
result.cache.l2 = util.getValue(lines, 'l2cachesize', ':');
result.cache.l3 = util.getValue(lines, 'l3cachesize', ':');
if (result.cache.l2) { result.cache.l2 = parseInt(result.cache.l2, 10) * 1024; }
if (result.cache.l3) { result.cache.l3 = parseInt(result.cache.l3, 10) * 1024; }
result.vendor = util.getValue(lines, 'manufacturer', ':');
result.speedMax = Math.round(parseFloat(util.getValue(lines, 'maxclockspeed', ':').replace(/,/g, '.')) / 10.0) / 100;
if (result.speed === 0 && (result.brand.indexOf('AMD') > -1 || result.brand.toLowerCase().indexOf('ryzen') > -1)) {
result.speed = getAMDSpeed(result.brand);
}
if (result.speed === 0) {
result.speed = result.speedMax;
}
result.speedMin = result.speed;
let description = util.getValue(lines, 'description', ':').split(' ');
for (let i = 0; i < description.length; i++) {
if (description[i].toLowerCase().startsWith('family') && (i + 1) < description.length && description[i + 1]) {
result.family = description[i + 1];
}
if (description[i].toLowerCase().startsWith('model') && (i + 1) < description.length && description[i + 1]) {
result.model = description[i + 1];
}
if (description[i].toLowerCase().startsWith('stepping') && (i + 1) < description.length && description[i + 1]) {
result.stepping = description[i + 1];
}
}
// socket type
const socketId = util.getValue(lines, 'UpgradeMethod', ':');
if (socketTypes[socketId]) {
result.socket = socketTypes[socketId];
}
// # threads / # cores
const countProcessors = util.countLines(lines, 'Caption');
const countThreads = util.getValue(lines, 'NumberOfLogicalProcessors', ':');
const countCores = util.getValue(lines, 'NumberOfCores', ':');
if (countProcessors) {
result.processors = parseInt(countProcessors) || 1;
}
if (countCores && countThreads) {
result.cores = parseInt(countThreads) || util.cores();
result.physicalCores = parseInt(countCores) || util.cores();
}
if (countProcessors > 1) {
result.cores = result.cores * countProcessors;
result.physicalCores = result.physicalCores * countProcessors;
}
const parts = data[1].split(/\n\s*\n/);
parts.forEach(function (part) {
lines = part.split('\r\n');
const cacheType = util.getValue(lines, 'CacheType');
const level = util.getValue(lines, 'Level');
const installedSize = util.getValue(lines, 'InstalledSize');
// L1 Instructions
if (level === '3' && cacheType === '3') {
result.cache.l1i = parseInt(installedSize, 10);
}
// L1 Data
if (level === '3' && cacheType === '4') {
result.cache.l1d = parseInt(installedSize, 10);
}
// L1 all
if (level === '3' && cacheType === '5' && !result.cache.l1i && !result.cache.l1d) {
result.cache.l1i = parseInt(installedSize, 10) / 2;
result.cache.l1d = parseInt(installedSize, 10) / 2;
}
});
// lines = data[2].split('\r\n');
// result.virtualization = (util.getValue(lines, 'HyperVRequirementVirtualizationFirmwareEnabled').toLowerCase() === 'true');
// result.virtualization = (util.getValue(lines, 'HyperVisorPresent').toLowerCase() === 'true');
const hyperv = data[2] ? data[2].toString().toLowerCase() : '';
result.virtualization = hyperv.indexOf('true') !== -1;
resolve(result);
});
} catch (e) {
resolve(result);
}
}
});
});
});
}
// --------------------------
// CPU - Processor Data
function cpu(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
getCpu().then(result => {
if (callback) { callback(result); }
resolve(result);
});
});
});
}
exports.cpu = cpu;
// --------------------------
// CPU - current speed - in GHz
function getCpuCurrentSpeedSync() {
let cpus = os.cpus();
let minFreq = 999999999;
let maxFreq = 0;
let avgFreq = 0;
let cores = [];
if (cpus && cpus.length) {
for (let i in cpus) {
if ({}.hasOwnProperty.call(cpus, i)) {
let freq = cpus[i].speed > 100 ? (cpus[i].speed + 1) / 1000 : cpus[i].speed / 10;
avgFreq = avgFreq + freq;
if (freq > maxFreq) { maxFreq = freq; }
if (freq < minFreq) { minFreq = freq; }
cores.push(parseFloat(freq.toFixed(2)));
}
}
avgFreq = avgFreq / cpus.length;
return {
min: parseFloat(minFreq.toFixed(2)),
max: parseFloat(maxFreq.toFixed(2)),
avg: parseFloat((avgFreq).toFixed(2)),
cores: cores
};
} else {
return {
min: 0,
max: 0,
avg: 0,
cores: cores
};
}
}
function cpuCurrentSpeed(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
let result = getCpuCurrentSpeedSync();
if (result.avg === 0 && _cpu_speed !== 0) {
const currCpuSpeed = parseFloat(_cpu_speed);
result = {
min: currCpuSpeed,
max: currCpuSpeed,
avg: currCpuSpeed,
cores: []
};
}
if (callback) { callback(result); }
resolve(result);
});
});
}
exports.cpuCurrentSpeed = cpuCurrentSpeed;
// --------------------------
// CPU - temperature
// if sensors are installed
function cpuTemperature(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
let result = {
main: null,
cores: [],
max: null,
socket: [],
chipset: null
};
if (_linux) {
// CPU Chipset, Socket
try {
const cmd = 'cat /sys/class/thermal/thermal_zone*/type 2>/dev/null; echo "-----"; cat /sys/class/thermal/thermal_zone*/temp 2>/dev/null;';
const parts = execSync(cmd).toString().split('-----\n');
if (parts.length === 2) {
const lines = parts[0].split('\n');
const lines2 = parts[1].split('\n');
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line.startsWith('acpi') && lines2[i]) {
result.socket.push(Math.round(parseInt(lines2[i], 10) / 100) / 10);
}
if (line.startsWith('pch') && lines2[i]) {
result.chipset = Math.round(parseInt(lines2[i], 10) / 100) / 10;
}
}
}
} catch (e) {
util.noop();
}
const cmd = 'for mon in /sys/class/hwmon/hwmon*; do for label in "$mon"/temp*_label; do if [ -f $label ]; then value=$(echo $label | rev | cut -c 7- | rev)_input; if [ -f "$value" ]; then echo $(cat "$label")___$(cat "$value"); fi; fi; done; done;';
try {
exec(cmd, function (error, stdout) {
stdout = stdout.toString();
const tdiePos = stdout.toLowerCase().indexOf('tdie');
if (tdiePos !== -1) {
stdout = stdout.substring(tdiePos);
}
let lines = stdout.split('\n');
lines.forEach(line => {
const parts = line.split('___');
const label = parts[0];
const value = parts.length > 1 && parts[1] ? parts[1] : '0';
if (value && (label === undefined || (label && label.toLowerCase().startsWith('core')))) {
result.cores.push(Math.round(parseInt(value, 10) / 100) / 10);
} else if (value && label && result.main === null) {
result.main = Math.round(parseInt(value, 10) / 100) / 10;
}
});
if (result.cores.length > 0) {
if (result.main === null) {
result.main = Math.round(result.cores.reduce((a, b) => a + b, 0) / result.cores.length);
}
let maxtmp = Math.max.apply(Math, result.cores);
result.max = (maxtmp > result.main) ? maxtmp : result.main;
}
if (result.main !== null) {
if (result.max === null) {
result.max = result.main;
}
if (callback) { callback(result); }
resolve(result);
return;
}
exec('sensors', function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
let tdieTemp = null;
let newSectionStarts = true;
let section = '';
lines.forEach(function (line) {
// determine section
if (line.trim() === '') {
newSectionStarts = true;
} else if (newSectionStarts) {
if (line.trim().toLowerCase().startsWith('acpi')) { section = 'acpi'; }
if (line.trim().toLowerCase().startsWith('pch')) { section = 'pch'; }
if (line.trim().toLowerCase().startsWith('core')) { section = 'core'; }
newSectionStarts = false;
}
let regex = /[+-]([^°]*)/g;
let temps = line.match(regex);
let firstPart = line.split(':')[0].toUpperCase();
if (section === 'acpi') {
// socket temp
if (firstPart.indexOf('TEMP') !== -1) {
result.socket.push(parseFloat(temps));
}
} else if (section === 'pch') {
// chipset temp
if (firstPart.indexOf('TEMP') !== -1) {
result.chipset = parseFloat(temps);
}
}
// cpu temp
if (firstPart.indexOf('PHYSICAL') !== -1 || firstPart.indexOf('PACKAGE') !== -1) {
result.main = parseFloat(temps);
}
if (firstPart.indexOf('CORE ') !== -1) {
result.cores.push(parseFloat(temps));
}
if (firstPart.indexOf('TDIE') !== -1 && tdieTemp === null) {
tdieTemp = parseFloat(temps);
}
});
if (result.cores.length > 0) {
if (result.main === null) {
result.main = Math.round(result.cores.reduce((a, b) => a + b, 0) / result.cores.length);
}
let maxtmp = Math.max.apply(Math, result.cores);
result.max = (maxtmp > result.main) ? maxtmp : result.main;
} else {
if (result.main === null && tdieTemp !== null) {
result.main = tdieTemp;
result.max = tdieTemp;
}
}
if (result.main !== null || result.max !== null) {
if (callback) { callback(result); }
resolve(result);
return;
}
}
fs.stat('/sys/class/thermal/thermal_zone0/temp', function (err) {
if (err === null) {
fs.readFile('/sys/class/thermal/thermal_zone0/temp', function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
if (lines.length > 0) {
result.main = parseFloat(lines[0]) / 1000.0;
result.max = result.main;
}
}
if (callback) { callback(result); }
resolve(result);
});
} else {
exec('/opt/vc/bin/vcgencmd measure_temp', function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
if (lines.length > 0 && lines[0].indexOf('=')) {
result.main = parseFloat(lines[0].split('=')[1]);
result.max = result.main;
}
}
if (callback) { callback(result); }
resolve(result);
});
}
});
});
});
} catch (er) {
if (callback) { callback(result); }
resolve(result);
}
}
if (_freebsd || _openbsd || _netbsd) {
exec('sysctl dev.cpu | grep temp', function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
let sum = 0;
lines.forEach(function (line) {
const parts = line.split(':');
if (parts.length > 1) {
const temp = parseFloat(parts[1].replace(',', '.'));
if (temp > result.max) { result.max = temp; }
sum = sum + temp;
result.cores.push(temp);
}
});
if (result.cores.length) {
result.main = Math.round(sum / result.cores.length * 100) / 100;
}
}
if (callback) { callback(result); }
resolve(result);
});
}
if (_darwin) {
let osxTemp = null;
try {
osxTemp = require('osx-temperature-sensor');
} catch (er) {
osxTemp = null;
}
if (osxTemp) {
result = osxTemp.cpuTemperature();
}
if (callback) { callback(result); }
resolve(result);
}
if (_sunos) {
if (callback) { callback(result); }
resolve(result);
}
if (_windows) {
try {
util.powerShell('Get-WmiObject MSAcpi_ThermalZoneTemperature -Namespace "root/wmi" | Select CurrentTemperature').then((stdout, error) => {
if (!error) {
let sum = 0;
let lines = stdout.split('\r\n').filter(line => line.trim() !== '').filter((line, idx) => idx > 0);
lines.forEach(function (line) {
let value = (parseInt(line, 10) - 2732) / 10;
sum = sum + value;
if (value > result.max) { result.max = value; }
result.cores.push(value);
});
if (result.cores.length) {
result.main = sum / result.cores.length;
}
}
if (callback) { callback(result); }
resolve(result);
});
} catch (e) {
if (callback) { callback(result); }
resolve(result);
}
}
});
});
}
exports.cpuTemperature = cpuTemperature;
// --------------------------
// CPU Flags
function cpuFlags(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
let result = '';
if (_windows) {
try {
exec('reg query "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0" /v FeatureSet', util.execOptsWin, function (error, stdout) {
if (!error) {
let flag_hex = stdout.split('0x').pop().trim();
let flag_bin_unpadded = parseInt(flag_hex, 16).toString(2);
let flag_bin = '0'.repeat(32 - flag_bin_unpadded.length) + flag_bin_unpadded;
// empty flags are the reserved fields in the CPUID feature bit list
// as found on wikipedia:
// https://en.wikipedia.org/wiki/CPUID
let all_flags = [
'fpu', 'vme', 'de', 'pse', 'tsc', 'msr', 'pae', 'mce', 'cx8', 'apic',
'', 'sep', 'mtrr', 'pge', 'mca', 'cmov', 'pat', 'pse-36', 'psn', 'clfsh',
'', 'ds', 'acpi', 'mmx', 'fxsr', 'sse', 'sse2', 'ss', 'htt', 'tm', 'ia64', 'pbe'
];
for (let f = 0; f < all_flags.length; f++) {
if (flag_bin[f] === '1' && all_flags[f] !== '') {
result += ' ' + all_flags[f];
}
}
result = result.trim().toLowerCase();
}
if (callback) { callback(result); }
resolve(result);
});
} catch (e) {
if (callback) { callback(result); }
resolve(result);
}
}
if (_linux) {
try {
exec('export LC_ALL=C; lscpu; unset LC_ALL', function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
lines.forEach(function (line) {
if (line.split(':')[0].toUpperCase().indexOf('FLAGS') !== -1) {
result = line.split(':')[1].trim().toLowerCase();
}
});
}
if (!result) {
fs.readFile('/proc/cpuinfo', function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
result = util.getValue(lines, 'features', ':', true).toLowerCase();
}
if (callback) { callback(result); }
resolve(result);
});
} else {
if (callback) { callback(result); }
resolve(result);
}
});
} catch (e) {
if (callback) { callback(result); }
resolve(result);
}
}
if (_freebsd || _openbsd || _netbsd) {
exec('export LC_ALL=C; dmidecode -t 4 2>/dev/null; unset LC_ALL', function (error, stdout) {
let flags = [];
if (!error) {
let parts = stdout.toString().split('\tFlags:');
const lines = parts.length > 1 ? parts[1].split('\tVersion:')[0].split('\n') : [];
lines.forEach(function (line) {
let flag = (line.indexOf('(') ? line.split('(')[0].toLowerCase() : '').trim().replace(/\t/g, '');
if (flag) {
flags.push(flag);
}
});
}
result = flags.join(' ').trim().toLowerCase();
if (callback) { callback(result); }
resolve(result);
});
}
if (_darwin) {
exec('sysctl machdep.cpu.features', function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
if (lines.length > 0 && lines[0].indexOf('machdep.cpu.features:') !== -1) {
result = lines[0].split(':')[1].trim().toLowerCase();
}
}
if (callback) { callback(result); }
resolve(result);
});
}
if (_sunos) {
if (callback) { callback(result); }
resolve(result);
}
});
});
}
exports.cpuFlags = cpuFlags;
// --------------------------
// CPU Cache
function cpuCache(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
let result = {
l1d: null,
l1i: null,
l2: null,
l3: null,
};
if (_linux) {
try {
exec('export LC_ALL=C; lscpu; unset LC_ALL', function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
lines.forEach(function (line) {
let parts = line.split(':');
if (parts[0].toUpperCase().indexOf('L1D CACHE') !== -1) {
result.l1d = parseInt(parts[1].trim()) * (parts[1].indexOf('M') !== -1 ? 1024 * 1024 : (parts[1].indexOf('K') !== -1 ? 1024 : 1));
}
if (parts[0].toUpperCase().indexOf('L1I CACHE') !== -1) {
result.l1i = parseInt(parts[1].trim()) * (parts[1].indexOf('M') !== -1 ? 1024 * 1024 : (parts[1].indexOf('K') !== -1 ? 1024 : 1));
}
if (parts[0].toUpperCase().indexOf('L2 CACHE') !== -1) {
result.l2 = parseInt(parts[1].trim()) * (parts[1].indexOf('M') !== -1 ? 1024 * 1024 : (parts[1].indexOf('K') !== -1 ? 1024 : 1));
}
if (parts[0].toUpperCase().indexOf('L3 CACHE') !== -1) {
result.l3 = parseInt(parts[1].trim()) * (parts[1].indexOf('M') !== -1 ? 1024 * 1024 : (parts[1].indexOf('K') !== -1 ? 1024 : 1));
}
});
}
if (callback) { callback(result); }
resolve(result);
});
} catch (e) {
if (callback) { callback(result); }
resolve(result);
}
}
if (_freebsd || _openbsd || _netbsd) {
exec('export LC_ALL=C; dmidecode -t 7 2>/dev/null; unset LC_ALL', function (error, stdout) {
let cache = [];
if (!error) {
const data = stdout.toString();
cache = data.split('Cache Information');
cache.shift();
}
for (let i = 0; i < cache.length; i++) {
const lines = cache[i].split('\n');
let cacheType = util.getValue(lines, 'Socket Designation').toLowerCase().replace(' ', '-').split('-');
cacheType = cacheType.length ? cacheType[0] : '';
const sizeParts = util.getValue(lines, 'Installed Size').split(' ');
let size = parseInt(sizeParts[0], 10);
const unit = sizeParts.length > 1 ? sizeParts[1] : 'kb';
size = size * (unit === 'kb' ? 1024 : (unit === 'mb' ? 1024 * 1024 : (unit === 'gb' ? 1024 * 1024 * 1024 : 1)));
if (cacheType) {
if (cacheType === 'l1') {
result.cache[cacheType + 'd'] = size / 2;
result.cache[cacheType + 'i'] = size / 2;
} else {
result.cache[cacheType] = size;
}
}
}
if (callback) { callback(result); }
resolve(result);
});
}
if (_darwin) {
exec('sysctl hw.l1icachesize hw.l1dcachesize hw.l2cachesize hw.l3cachesize', function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
lines.forEach(function (line) {
let parts = line.split(':');
if (parts[0].toLowerCase().indexOf('hw.l1icachesize') !== -1) {
result.l1d = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
}
if (parts[0].toLowerCase().indexOf('hw.l1dcachesize') !== -1) {
result.l1i = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
}
if (parts[0].toLowerCase().indexOf('hw.l2cachesize') !== -1) {
result.l2 = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
}
if (parts[0].toLowerCase().indexOf('hw.l3cachesize') !== -1) {
result.l3 = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
}
});
}
if (callback) { callback(result); }
resolve(result);
});
}
if (_sunos) {
if (callback) { callback(result); }
resolve(result);
}
if (_windows) {
try {
util.powerShell('Get-WmiObject Win32_processor | select L2CacheSize, L3CacheSize | fl').then((stdout, error) => {
if (!error) {
let lines = stdout.split('\r\n');
result.l1d = 0;
result.l1i = 0;
result.l2 = util.getValue(lines, 'l2cachesize', ':');
result.l3 = util.getValue(lines, 'l3cachesize', ':');
if (result.l2) { result.l2 = parseInt(result.l2, 10) * 1024; }
if (result.l3) { result.l3 = parseInt(result.l3, 10) * 1024; }
}
util.powerShell('Get-WmiObject Win32_CacheMemory | select CacheType,InstalledSize,Level | fl').then((stdout, error) => {
if (!error) {
const parts = stdout.split(/\n\s*\n/);
parts.forEach(function (part) {
const lines = part.split('\r\n');
const cacheType = util.getValue(lines, 'CacheType');
const level = util.getValue(lines, 'Level');
const installedSize = util.getValue(lines, 'InstalledSize');
// L1 Instructions
if (level === '3' && cacheType === '3') {
result.l1i = parseInt(installedSize, 10);
}
// L1 Data
if (level === '3' && cacheType === '4') {
result.l1d = parseInt(installedSize, 10);
}
// L1 all
if (level === '3' && cacheType === '5' && !result.l1i && !result.l1d) {
result.l1i = parseInt(installedSize, 10) / 2;
result.l1d = parseInt(installedSize, 10) / 2;
}
});
}
if (callback) { callback(result); }
resolve(result);
});
});
} catch (e) {
if (callback) { callback(result); }
resolve(result);
}
}
});
});
}
exports.cpuCache = cpuCache;
// --------------------------
// CPU - current load - in %
function getLoad() {
return new Promise((resolve) => {
process.nextTick(() => {
let loads = os.loadavg().map(function (x) { return x / util.cores(); });
let avgLoad = parseFloat((Math.max.apply(Math, loads)).toFixed(2));
let result = {};
let now = Date.now() - _current_cpu.ms;
if (now >= 200) {
_current_cpu.ms = Date.now();
const cpus = os.cpus();
let totalUser = 0;
let totalSystem = 0;
let totalNice = 0;
let totalIrq = 0;
let totalIdle = 0;
let cores = [];
_corecount = (cpus && cpus.length) ? cpus.length : 0;
for (let i = 0; i < _corecount; i++) {
const cpu = cpus[i].times;
totalUser += cpu.user;
totalSystem += cpu.sys;
totalNice += cpu.nice;
totalIdle += cpu.idle;
totalIrq += cpu.irq;
let tmpTick = (_cpus && _cpus[i] && _cpus[i].totalTick ? _cpus[i].totalTick : 0);
let tmpLoad = (_cpus && _cpus[i] && _cpus[i].totalLoad ? _cpus[i].totalLoad : 0);
let tmpUser = (_cpus && _cpus[i] && _cpus[i].user ? _cpus[i].user : 0);
let tmpSystem = (_cpus && _cpus[i] && _cpus[i].sys ? _cpus[i].sys : 0);
let tmpNice = (_cpus && _cpus[i] && _cpus[i].nice ? _cpus[i].nice : 0);
let tmpIdle = (_cpus && _cpus[i] && _cpus[i].idle ? _cpus[i].idle : 0);
let tmpIrq = (_cpus && _cpus[i] && _cpus[i].irq ? _cpus[i].irq : 0);
_cpus[i] = cpu;
_cpus[i].totalTick = _cpus[i].user + _cpus[i].sys + _cpus[i].nice + _cpus[i].irq + _cpus[i].idle;
_cpus[i].totalLoad = _cpus[i].user + _cpus[i].sys + _cpus[i].nice + _cpus[i].irq;
_cpus[i].currentTick = _cpus[i].totalTick - tmpTick;
_cpus[i].load = (_cpus[i].totalLoad - tmpLoad);
_cpus[i].loadUser = (_cpus[i].user - tmpUser);
_cpus[i].loadSystem = (_cpus[i].sys - tmpSystem);
_cpus[i].loadNice = (_cpus[i].nice - tmpNice);
_cpus[i].loadIdle = (_cpus[i].idle - tmpIdle);
_cpus[i].loadIrq = (_cpus[i].irq - tmpIrq);
cores[i] = {};
cores[i].load = _cpus[i].load / _cpus[i].currentTick * 100;
cores[i].loadUser = _cpus[i].loadUser / _cpus[i].currentTick * 100;
cores[i].loadSystem = _cpus[i].loadSystem / _cpus[i].currentTick * 100;
cores[i].loadNice = _cpus[i].loadNice / _cpus[i].currentTick * 100;
cores[i].loadIdle = _cpus[i].loadIdle / _cpus[i].currentTick * 100;
cores[i].loadIrq = _cpus[i].loadIrq / _cpus[i].currentTick * 100;
cores[i].rawLoad = _cpus[i].load;
cores[i].rawLoadUser = _cpus[i].loadUser;
cores[i].rawLoadSystem = _cpus[i].loadSystem;
cores[i].rawLoadNice = _cpus[i].loadNice;
cores[i].rawLoadIdle = _cpus[i].loadIdle;
cores[i].rawLoadIrq = _cpus[i].loadIrq;
}
let totalTick = totalUser + totalSystem + totalNice + totalIrq + totalIdle;
let totalLoad = totalUser + totalSystem + totalNice + totalIrq;
let currentTick = totalTick - _current_cpu.tick;
result = {
avgLoad: avgLoad,
currentLoad: (totalLoad - _current_cpu.load) / currentTick * 100,
currentLoadUser: (totalUser - _current_cpu.user) / currentTick * 100,
currentLoadSystem: (totalSystem - _current_cpu.system) / currentTick * 100,
currentLoadNice: (totalNice - _current_cpu.nice) / currentTick * 100,
currentLoadIdle: (totalIdle - _current_cpu.idle) / currentTick * 100,
currentLoadIrq: (totalIrq - _current_cpu.irq) / currentTick * 100,
rawCurrentLoad: (totalLoad - _current_cpu.load),
rawCurrentLoadUser: (totalUser - _current_cpu.user),
rawCurrentLoadSystem: (totalSystem - _current_cpu.system),
rawCurrentLoadNice: (totalNice - _current_cpu.nice),
rawCurrentLoadIdle: (totalIdle - _current_cpu.idle),
rawCurrentLoadIrq: (totalIrq - _current_cpu.irq),
cpus: cores
};
_current_cpu = {
user: totalUser,
nice: totalNice,
system: totalSystem,
idle: totalIdle,
irq: totalIrq,
tick: totalTick,
load: totalLoad,
ms: _current_cpu.ms,
currentLoad: result.currentLoad,
currentLoadUser: result.currentLoadUser,
currentLoadSystem: result.currentLoadSystem,
currentLoadNice: result.currentLoadNice,
currentLoadIdle: result.currentLoadIdle,
currentLoadIrq: result.currentLoadIrq,
rawCurrentLoad: result.rawCurrentLoad,
rawCurrentLoadUser: result.rawCurrentLoadUser,
rawCurrentLoadSystem: result.rawCurrentLoadSystem,
rawCurrentLoadNice: result.rawCurrentLoadNice,
rawCurrentLoadIdle: result.rawCurrentLoadIdle,
rawCurrentLoadIrq: result.rawCurrentLoadIrq,
};
} else {
let cores = [];
for (let i = 0; i < _corecount; i++) {
cores[i] = {};
cores[i].load = _cpus[i].load / _cpus[i].currentTick * 100;
cores[i].loadUser = _cpus[i].loadUser / _cpus[i].currentTick * 100;
cores[i].loadSystem = _cpus[i].loadSystem / _cpus[i].currentTick * 100;
cores[i].loadNice = _cpus[i].loadNice / _cpus[i].currentTick * 100;
cores[i].loadIdle = _cpus[i].loadIdle / _cpus[i].currentTick * 100;
cores[i].loadIrq = _cpus[i].loadIrq / _cpus[i].currentTick * 100;
cores[i].rawLoad = _cpus[i].load;
cores[i].rawLoadUser = _cpus[i].loadUser;
cores[i].rawLoadSystem = _cpus[i].loadSystem;
cores[i].rawLoadNice = _cpus[i].loadNice;
cores[i].rawLoadIdle = _cpus[i].loadIdle;
cores[i].rawLoadIrq = _cpus[i].loadIrq;
}
result = {
avgLoad: avgLoad,
currentLoad: _current_cpu.currentLoad,
currentLoadUser: _current_cpu.currentLoadUser,
currentLoadSystem: _current_cpu.currentLoadSystem,
currentLoadNice: _current_cpu.currentLoadNice,
currentLoadIdle: _current_cpu.currentLoadIdle,
currentLoadIrq: _current_cpu.currentLoadIrq,
rawCurrentLoad: _current_cpu.rawCurrentLoad,
rawCurrentLoadUser: _current_cpu.rawCurrentLoadUser,
rawCurrentLoadSystem: _current_cpu.rawCurrentLoadSystem,
rawCurrentLoadNice: _current_cpu.rawCurrentLoadNice,
rawCurrentLoadIdle: _current_cpu.rawCurrentLoadIdle,
rawCurrentLoadIrq: _current_cpu.rawCurrentLoadIrq,
cpus: cores
};
}
resolve(result);
});
});
}
function currentLoad(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
getLoad().then(result => {
if (callback) { callback(result); }
resolve(result);
});
});
});
}
exports.currentLoad = currentLoad;
// --------------------------
// PS - full load
// since bootup
function getFullLoad() {
return new Promise((resolve) => {
process.nextTick(() => {
const cpus = os.cpus();
let totalUser = 0;
let totalSystem = 0;
let totalNice = 0;
let totalIrq = 0;
let totalIdle = 0;
let result = 0;
if (cpus && cpus.length) {
for (let i = 0, len = cpus.length; i < len; i++) {
const cpu = cpus[i].times;
totalUser += cpu.user;
totalSystem += cpu.sys;
totalNice += cpu.nice;
totalIrq += cpu.irq;
totalIdle += cpu.idle;
}
let totalTicks = totalIdle + totalIrq + totalNice + totalSystem + totalUser;
result = (totalTicks - totalIdle) / totalTicks * 100.0;
} else {
result = 0;
}
resolve(result);
});
});
}
function fullLoad(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
getFullLoad().then(result => {
if (callback) { callback(result); }
resolve(result);
});
});
});
}
exports.fullLoad = fullLoad;