lup-system
Version:
NodeJS library to retrieve system information and utilization.
329 lines (328 loc) • 14.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getMemoryInfo = getMemoryInfo;
exports.getMemoryUtilization = getMemoryUtilization;
const os_1 = __importDefault(require("os"));
const utils_1 = require("./utils");
/**
* Returns information about the memory (RAM).
*
* @returns Memory information.
*/
async function getMemoryInfo() {
const memoryInfo = {
size: os_1.default.totalmem(),
utilization: {
used: os_1.default.totalmem() - os_1.default.freemem(),
free: os_1.default.freemem(),
percentage: (os_1.default.totalmem() - os_1.default.freemem()) / os_1.default.totalmem(),
},
};
const interleavePositions = new Set();
switch (process.platform) {
case 'darwin':
case 'linux': {
const output = await (0, utils_1.execCommand)('dmidecode --type memory').catch(() => '');
const lines = output.split('\n');
let currDevice = null;
let ignoreBlock = true;
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < lines.length; i++) {
const [key, value] = lines[i].split(': ').map((s) => s.trim());
if (!key || !currDevice) {
// empty line marks new device
if (currDevice && Object.keys(currDevice).length > 0) {
memoryInfo.devices = memoryInfo.devices || [];
memoryInfo.devices.push(currDevice);
}
currDevice = {};
ignoreBlock = true;
continue;
}
if (!value) {
ignoreBlock = ignoreBlock || key === 'Memory Device';
continue; // skip lines without value
}
if (ignoreBlock)
continue; // skip block if marked to ignore
if (key === 'Total Width' || key === 'Data Width') {
const busWidth = parseInt(value.split(' ')[0], 10); // strip unit 'bits'
if (!Number.isNaN(busWidth))
currDevice.busWidth = busWidth;
}
else if (key === 'Size') {
const size = parseInt(value.split(' ')[0], 10); // strip unit 'MB'
if (!Number.isNaN(size))
currDevice.size = size * 1024 * 1024; // convert MB to bytes
}
else if (key === 'Locator' || key === 'Socket Designation') {
currDevice.locator = value;
}
else if (key === 'Bank Locator') {
currDevice.bankName = value;
}
else if (key === 'Type') {
currDevice.type = value;
}
else if (key === 'Speed') {
const mhz = parseInt(value.split(' ')[0], 10); // strip unit 'MHz'
if (!Number.isNaN(mhz)) {
currDevice.clockSpeed = mhz;
currDevice.maxClockSpeed = mhz; // use max speed as default clock speed
}
}
else if (key === 'Configured Memory Speed' || key === 'Configured Clock Speed') {
const mhz = parseInt(value.split(' ')[0], 10); // strip unit 'MHz'
if (!Number.isNaN(mhz)) {
currDevice.clockSpeed = mhz;
if (!currDevice.maxClockSpeed)
currDevice.maxClockSpeed = mhz; // use configured speed as default max speed
}
}
else if (key === 'Manufacturer') {
currDevice.manufacturer = value;
}
else if (key === 'Part Number') {
currDevice.model = currDevice.model || value; // use first available model
}
else if (key === 'Rank') {
const rank = parseInt(value, 10);
if (!Number.isNaN(rank))
interleavePositions.add(rank);
}
else if (key === 'Voltage' || key === 'Configured Voltage') {
const voltage = parseFloat(value.split(' ')[0]); // strip unit 'V'
if (!Number.isNaN(voltage))
currDevice.voltage = voltage; // keep in volts
}
}
break;
}
case 'win32': {
const output = await (0, utils_1.execCommand)('powershell -Command "Get-CimInstance -ClassName Win32_PhysicalMemory | Format-List"').catch(() => '');
const lines = output.split('\n');
let currDevice = null;
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < lines.length; i++) {
const [key, value] = lines[i].split(' : ').map((s) => s.trim());
if (!key || !currDevice) {
// empty line marks new device
if (currDevice && Object.keys(currDevice).length > 0) {
memoryInfo.devices = memoryInfo.devices || [];
memoryInfo.devices.push(currDevice);
}
currDevice = {};
continue;
}
if (!value)
continue; // skip empty lines
if (key === 'Manufacturer') {
currDevice.manufacturer = value;
}
else if (key === 'Model' || key === 'PartNumber') {
currDevice.model = currDevice.model || value;
}
else if (key === 'BankLabel') {
currDevice.bankName = value;
}
else if (key === 'Capacity') {
const size = parseInt(value, 10);
if (!Number.isNaN(size))
currDevice.size = size;
}
else if (key === 'DataWidth' || key === 'TotalWidth') {
const busWidth = parseInt(value, 10);
if (!Number.isNaN(busWidth))
currDevice.busWidth = busWidth;
}
else if (key === 'InterleavePosition') {
const position = parseInt(value, 10);
if (!Number.isNaN(position))
interleavePositions.add(position);
}
else if (key === 'Speed') {
const mhz = parseInt(value, 10);
if (!Number.isNaN(mhz)) {
currDevice.maxClockSpeed = mhz;
if (!currDevice.clockSpeed)
currDevice.clockSpeed = mhz; // use max speed as default clock speed
}
}
else if (key === 'ConfiguredClockSpeed' || key === 'ConfiguredMemorySpeed') {
// higher priority than Speed
const mhz = parseInt(value, 10);
if (!Number.isNaN(mhz)) {
currDevice.clockSpeed = mhz;
if (!currDevice.maxClockSpeed)
currDevice.maxClockSpeed = mhz; // use configured speed as default max speed
}
}
else if (key === 'ConfiguredVoltage' || key === 'Voltage') {
const voltage = parseFloat(value);
if (!Number.isNaN(voltage))
currDevice.voltage = voltage / 1000; // convert from mV to V
}
else if (key === 'DeviceLocator') {
currDevice.locator = value;
}
else if (key === 'SMBIOSMemoryType') {
switch (value) {
case '0':
currDevice.type = 'Unknown';
break;
case '1':
currDevice.type = 'Other';
break;
case '2':
currDevice.type = 'DRAM';
break;
case '3':
currDevice.type = 'Synchronous DRAM';
break;
case '4':
currDevice.type = 'Cache DRAM';
break;
case '5':
currDevice.type = 'EDO';
break;
case '6':
currDevice.type = 'EDRAM';
break;
case '7':
currDevice.type = 'VRAM';
break;
case '8':
currDevice.type = 'SRAM';
break;
case '9':
currDevice.type = 'RAM';
break;
case '10':
currDevice.type = 'ROM';
break;
case '11':
currDevice.type = 'Flash';
break;
case '12':
currDevice.type = 'EEPROM';
break;
case '13':
currDevice.type = 'FEPROM';
break;
case '14':
currDevice.type = 'EPROM';
break;
case '15':
currDevice.type = 'CDRAM';
break;
case '16':
currDevice.type = '3DRAM';
break;
case '17':
currDevice.type = 'SDRAM';
break;
case '18':
currDevice.type = 'SGRAM';
break;
case '19':
currDevice.type = 'RDRAM';
break;
case '20':
currDevice.type = 'DDR';
currDevice.transfersPerClockCycle = 2;
break;
case '21':
currDevice.type = 'DDR2';
currDevice.transfersPerClockCycle = 2;
break;
case '22':
currDevice.type = 'DDR2 FB-DIMM';
currDevice.transfersPerClockCycle = 2;
break;
case '24':
currDevice.type = 'DDR3';
currDevice.transfersPerClockCycle = 2;
break;
case '25':
currDevice.type = 'FBD2';
currDevice.transfersPerClockCycle = 2;
break;
case '26':
currDevice.type = 'DDR4';
currDevice.transfersPerClockCycle = 2;
break;
case '27':
currDevice.type = 'LPDDR';
currDevice.transfersPerClockCycle = 2;
break;
case '28':
currDevice.type = 'LPDDR2';
currDevice.transfersPerClockCycle = 2;
break;
case '29':
currDevice.type = 'LPDDR3';
currDevice.transfersPerClockCycle = 2;
break;
case '30':
currDevice.type = 'LPDDR4';
currDevice.transfersPerClockCycle = 2;
break;
case '34':
currDevice.type = 'HBM';
currDevice.transfersPerClockCycle = 2;
break;
case '35':
currDevice.type = 'HBM2';
currDevice.transfersPerClockCycle = 2;
break;
case '36':
currDevice.type = 'DDR5';
currDevice.transfersPerClockCycle = 2;
break;
case '37':
currDevice.type = 'LPDDR5';
currDevice.transfersPerClockCycle = 2;
break;
// TODO keep up to date
}
}
}
break;
}
}
// post-processing
if (memoryInfo.devices) {
const parallelism = Math.max(1, interleavePositions.size);
let clockSpeed;
let busWidth;
let transfersPerCycle;
for (const device of memoryInfo.devices) {
if (device.size && device.busWidth && device.clockSpeed) {
clockSpeed = clockSpeed ? Math.min(clockSpeed, device.clockSpeed) : device.clockSpeed;
busWidth = busWidth ? Math.min(busWidth, device.busWidth) : device.busWidth;
transfersPerCycle = transfersPerCycle
? Math.min(transfersPerCycle, device.transfersPerClockCycle ?? 1)
: device.transfersPerClockCycle;
device.bandwidth = ((device.clockSpeed * 1000 * 1000 * device.busWidth) / 8) * (transfersPerCycle ?? 1);
}
}
if (clockSpeed && busWidth)
memoryInfo.bandwidth = ((clockSpeed * 1000 * 1000 * busWidth) / 8) * (transfersPerCycle ?? 1) * parallelism; // bytes per second
}
return memoryInfo;
}
/**
* Returns memory utilization data.
*
* @returns Memory utilization data.
*/
async function getMemoryUtilization() {
return {
used: os_1.default.totalmem() - os_1.default.freemem(),
free: os_1.default.freemem(),
percentage: (os_1.default.totalmem() - os_1.default.freemem()) / os_1.default.totalmem(),
};
}