node-os-utils
Version:
An operating system utility library.
177 lines (153 loc) • 4.93 kB
JavaScript
/**
* @Author: 王澍(SunilWang)
* @Date: 2017-7-9 21:49:00
* @Last Modified by: 王澍(SunilWang)
* @Last Modified time: 2020-09-10 14:59:41
* @Description:
*/
var bucket = require('./bucket')
var os = require('os')
var fs = require('fs')
var co = require('../util/co')
var util = require('../util')
var exec = require('./exec')
var linuxFreeMemory = function () {
return new Promise(function (resolve) {
// https://github.com/SunilWang/node-os-utils/pull/11
// running this on an embedded linux device. This steps takes around 500ms. With this change we brought it down to a few milliseconds.
fs.readFile('/proc/meminfo', 'utf8', function (err, out) {
if (err) {
return resolve(bucket.options.NOT_SUPPORTED_VALUE)
}
var memInfo = {}
var usage = out.toString().trim().split('\n')
usage.forEach((line) => {
var pair = line.split(':')
memInfo[pair[0]] = parseInt(pair[1], 10)
})
var totalMem = parseInt(memInfo.MemTotal, 10) * 1024
// check if MemAvailable exists
if (!memInfo.MemAvailable) {
memInfo.MemAvailable = memInfo['MemFree'] + memInfo['Buffers'] + memInfo['Cached'] + memInfo['SReclaimable'] - memInfo['Shmem'];
}
var freeMem = memInfo.MemAvailable * 1024
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
// https://www.cnblogs.com/johnnyzen/p/8011309.html
if (os.release() < '3.14') {
freeMem =
((memInfo.MemFree || 0) +
(memInfo.Buffers || 0) +
(memInfo.Cached || 0)) *
1024
}
return resolve({ totalMem, freeMem })
})
})
}
// learn from: https://github.com/X-Profiler/xtransit/blob/master/orders/system_log.js#L356
var osxFreeMemory = co.wrap(function* () {
var totalMem = os.totalmem()
var mappings = {
'Pages purgeable': 'purgeable',
'Pages wired down': 'wired',
'Pages active': 'active',
'Pages inactive': 'inactive',
'Pages occupied by compressor': 'compressed',
}
var [vmStat, pagePageable] = yield Promise.all([
exec('vm_stat'),
exec('sysctl vm.page_pageable_internal_count'),
])
vmStat = vmStat.toString().trim()
pagePageable = pagePageable.toString().trim()
// get page size
var pageSize = 4096
var matchdPageSize = /page size of (\d+) bytes/.exec(vmStat)
if (matchdPageSize && util.isNumber(matchdPageSize[1])) {
pageSize = Number(matchdPageSize[1])
}
// get page pageable
var [, pageableValue] = pagePageable.split(':')
if (!util.isNumber(pageableValue)) {
return {
totalMem,
freeMem: os.freemem(),
}
}
pageableValue = Number(pageableValue) * pageSize
// get vm stats
var lines = vmStat.split('\n').filter((x) => x !== '')
var stats = {}
lines.forEach((x) => {
var parts = x.split(':')
var key = parts[0]
var val = parts[1].replace('.', '').trim()
if (mappings[key]) {
var ky = mappings[key]
stats[ky] = val * pageSize
}
})
// get app memory
var appMemory = pageableValue - stats.purgeable
// get wired memory
var wiredMemory = stats.wired
// get compressed memory
var compressedMemory = stats.compressed
var used = appMemory + wiredMemory + compressedMemory
return {
totalMem,
freeMem: totalMem - used,
}
})
bucket.mem = {
info: co.wrap(function* () {
var totalMem = null
var freeMem = null
var memInfo = yield linuxFreeMemory()
if (bucket.isNotSupported(memInfo)) {
totalMem = os.totalmem()
freeMem = os.freemem()
if (os.platform() === 'darwin') {
var mem = yield osxFreeMemory()
totalMem = mem.totalMem
freeMem = mem.freeMem
}
} else {
totalMem = memInfo.totalMem
freeMem = memInfo.freeMem
}
var totalMemMb = parseFloat((totalMem / 1024 / 1024).toFixed(2))
var usedMemMb = parseFloat(((totalMem - freeMem) / 1024 / 1024).toFixed(2))
var freeMemMb = parseFloat((totalMemMb - usedMemMb).toFixed(2))
var usedMemPercentage = parseFloat((100 * ((totalMem - freeMem) / totalMem)).toFixed(2))
var freeMemPercentage = parseFloat((100 * (freeMem / totalMem)).toFixed(2))
return {
totalMemMb: totalMemMb,
usedMemMb: usedMemMb,
freeMemMb: freeMemMb,
usedMemPercentage: usedMemPercentage,
freeMemPercentage: freeMemPercentage,
}
}),
free: function () {
var self = this
return self.info().then(function (res) {
return Promise.resolve({
totalMemMb: res.totalMemMb,
freeMemMb: res.freeMemMb,
})
})
},
used: function () {
var self = this
return self.info().then(function (res) {
return Promise.resolve({
totalMemMb: res.totalMemMb,
usedMemMb: res.usedMemMb,
})
})
},
totalMem: function () {
return os.totalmem()
},
}