mem() added reclaimable (Linux, macOS)

This commit is contained in:
Sebastian Hildebrandt 2025-05-24 06:52:52 +02:00
parent 5b79685f5e
commit 63b01c4418
8 changed files with 76 additions and 16 deletions

View File

@ -90,6 +90,7 @@ For major (breaking) changes - **version 4, 3 and 2** - see end of page.
| Version | Date | Comment | | Version | Date | Comment |
| ------- | ---------- | --------------------------------------------------------------------------------------------------- | | ------- | ---------- | --------------------------------------------------------------------------------------------------- |
| 5.27.0 | 2025-05-24 | `mem()` added reclaimable (Linux, macOS) |
| 5.26.2 | 2025-05-23 | `memLayout()` manufacturers reference updated | | 5.26.2 | 2025-05-23 | `memLayout()` manufacturers reference updated |
| 5.26.1 | 2025-05-22 | `inetChecksite()` fix timeout | | 5.26.1 | 2025-05-22 | `inetChecksite()` fix timeout |
| 5.26.0 | 2025-05-21 | `getStatic()` added audio, usb, bluetooth, printer | | 5.26.0 | 2025-05-21 | `getStatic()` added audio, usb, bluetooth, printer |

View File

@ -31,9 +31,9 @@
## The Systeminformation Project ## The Systeminformation Project
This is amazing. Started as a small project just for myself, it now has > 17,000 This is amazing. Started as a small project just for myself, it now has > 17,000
lines of code, > 650 versions published, up to 8 mio downloads per month, > 330 lines of code, > 650 versions published, up to 8 mio downloads per month, > 350
mio downloads overall. #1 NPM ranking for backend packages. Thank you to all who mio downloads overall. Top 10 NPM ranking for backend packages. Thank you to all
contributed to this project! who contributed to this project!
> **Upcoming Version 6** ⭐️⭐️⭐️ > **Upcoming Version 6** ⭐️⭐️⭐️
> >
@ -163,6 +163,7 @@ si.cpu()
(last 7 major and minor version releases) (last 7 major and minor version releases)
- Version 5.27.0: `mem()` added reclaimable memory
- Version 5.26.0: `getStatic()`, `getAll()` added usb, audio, bluetooth, printer - Version 5.26.0: `getStatic()`, `getAll()` added usb, audio, bluetooth, printer
- Version 5.25.0: `versions()` added homebrew - Version 5.25.0: `versions()` added homebrew
- Version 5.24.0: `versions()` added bun and deno - Version 5.24.0: `versions()` added bun and deno
@ -338,6 +339,7 @@ Full function reference with examples can be found at
| | buffers | X | | | | | used by buffers | | | buffers | X | | | | | used by buffers |
| | cached | X | | | | | used by cache | | | cached | X | | | | | used by cache |
| | slab | X | | | | | used by slab | | | slab | X | | | | | used by slab |
| | reclaimable | X | | X | | | reclaimable (SReclaimable) |
| | available | X | X | X | X | X | potentially available (total - active) | | | available | X | X | X | X | X | potentially available (total - active) |
| | swaptotal | X | X | X | X | X | | | | swaptotal | X | X | X | X | X | |
| | swapused | X | X | X | X | X | | | | swapused | X | X | X | X | X | |

View File

@ -57,6 +57,11 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr>
<th scope="row">5.27.0</th>
<td>2024-05-24</td>
<td><span class="code">mem()</span> added reclaimable (linux, macOS)</td>
</tr>
<tr> <tr>
<th scope="row">5.26.2</th> <th scope="row">5.26.2</th>
<td>2024-05-23</td> <td>2024-05-23</td>

View File

@ -170,7 +170,7 @@
<img class="logo" src="assets/logo.png" alt="logo"> <img class="logo" src="assets/logo.png" alt="logo">
<div class="title">systeminformation</div> <div class="title">systeminformation</div>
<div class="subtitle"><span id="typed"></span>&nbsp;</div> <div class="subtitle"><span id="typed"></span>&nbsp;</div>
3<div class="version">New Version: <span id="version">5.26.2</span></div> 3<div class="version">New Version: <span id="version">5.27.0</span></div>
<button class="btn btn-light" onclick="location.href='https://github.com/sebhildebrandt/systeminformation'">View on Github <i class=" fab fa-github"></i></button> <button class="btn btn-light" onclick="location.href='https://github.com/sebhildebrandt/systeminformation'">View on Github <i class=" fab fa-github"></i></button>
</div> </div>
<div class="down"> <div class="down">

View File

@ -157,6 +157,16 @@
<td></td> <td></td>
<td>used by slab</td> <td>used by slab</td>
</tr> </tr>
<tr>
<td></td>
<td>reclaimable</td>
<td>X</td>
<td></td>
<td>X</td>
<td></td>
<td></td>
<td>reclaimable</td>
</tr>
<tr> <tr>
<td></td> <td></td>
<td>available</td> <td>available</td>

View File

@ -575,7 +575,7 @@ function blockDevices(callback) {
if (_linux) { if (_linux) {
// see https://wiki.ubuntuusers.de/lsblk/ // see https://wiki.ubuntuusers.de/lsblk/
// exec("lsblk -bo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,TRAN,SERIAL,LABEL,MODEL,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,SCHED,RQ-SIZE,RA,WSAME", function (error, stdout) { // exec("lsblk -bo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,TRAN,SERIAL,LABEL,MODEL,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,SCHED,RQ-SIZE,RA,WSAME", function (error, stdout) {
exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,TRAN,SERIAL,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, function (error, stdout) { const procLsblk1 = exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,TRAN,SERIAL,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
if (!error) { if (!error) {
let lines = blkStdoutToObject(stdout).split('\n'); let lines = blkStdoutToObject(stdout).split('\n');
data = parseBlk(lines); data = parseBlk(lines);
@ -586,7 +586,7 @@ function blockDevices(callback) {
} }
resolve(data); resolve(data);
} else { } else {
exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, function (error, stdout) { const procLsblk2 = exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
if (!error) { if (!error) {
let lines = blkStdoutToObject(stdout).split('\n'); let lines = blkStdoutToObject(stdout).split('\n');
data = parseBlk(lines); data = parseBlk(lines);
@ -597,11 +597,23 @@ function blockDevices(callback) {
} }
resolve(data); resolve(data);
}); });
procLsblk2.on('error', function () {
if (callback) {
callback(data);
} }
resolve(data);
});
}
});
procLsblk1.on('error', function () {
if (callback) {
callback(data);
}
resolve(data);
}); });
} }
if (_darwin) { if (_darwin) {
exec('diskutil info -all', { maxBuffer: 1024 * 1024 }, function (error, stdout) { const procDskutil = exec('diskutil info -all', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
if (!error) { if (!error) {
let lines = stdout.toString().split('\n'); let lines = stdout.toString().split('\n');
// parse lines into temp array of devices // parse lines into temp array of devices
@ -613,6 +625,12 @@ function blockDevices(callback) {
} }
resolve(data); resolve(data);
}); });
procDskutil.on('error', function () {
if (callback) {
callback(data);
}
resolve(data);
});
} }
if (_sunos) { if (_sunos) {
if (callback) { callback(data); } if (callback) { callback(data); }
@ -747,7 +765,7 @@ function fsStats(callback) {
if ((_fs_speed && !_fs_speed.ms) || (_fs_speed && _fs_speed.ms && Date.now() - _fs_speed.ms >= 500)) { if ((_fs_speed && !_fs_speed.ms) || (_fs_speed && _fs_speed.ms && Date.now() - _fs_speed.ms >= 500)) {
if (_linux) { if (_linux) {
// exec("df -k | grep /dev/", function(error, stdout) { // exec("df -k | grep /dev/", function(error, stdout) {
exec('lsblk -r 2>/dev/null | grep /', { maxBuffer: 1024 * 1024 }, function (error, stdout) { const procLsblk = exec('lsblk -r 2>/dev/null | grep /', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
if (!error) { if (!error) {
let lines = stdout.toString().split('\n'); let lines = stdout.toString().split('\n');
let fs_filter = []; let fs_filter = [];
@ -759,7 +777,7 @@ function fsStats(callback) {
}); });
let output = fs_filter.join('|'); let output = fs_filter.join('|');
exec('cat /proc/diskstats | egrep "' + output + '"', { maxBuffer: 1024 * 1024 }, function (error, stdout) { const procCat = exec('cat /proc/diskstats | egrep "' + output + '"', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
if (!error) { if (!error) {
let lines = stdout.toString().split('\n'); let lines = stdout.toString().split('\n');
lines.forEach(function (line) { lines.forEach(function (line) {
@ -778,6 +796,12 @@ function fsStats(callback) {
} }
resolve(result); resolve(result);
}); });
procCat.on('error', function () {
if (callback) {
callback(result);
}
resolve(result);
});
} else { } else {
if (callback) { if (callback) {
callback(result); callback(result);
@ -785,9 +809,16 @@ function fsStats(callback) {
resolve(result); resolve(result);
} }
}); });
procLsblk.on('error', function () {
if (callback) {
callback(result);
}
resolve(result);
});
} }
if (_darwin) { if (_darwin) {
exec('ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n "/IOBlockStorageDriver/,/Statistics/p" | grep "Statistics" | tr -cd "01234567890,\n"', { maxBuffer: 1024 * 1024 }, function (error, stdout) { const procIoreg = exec('ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n "/IOBlockStorageDriver/,/Statistics/p" | grep "Statistics" | tr -cd "01234567890,\n"', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
if (!error) { if (!error) {
let lines = stdout.toString().split('\n'); let lines = stdout.toString().split('\n');
lines.forEach(function (line) { lines.forEach(function (line) {
@ -806,6 +837,12 @@ function fsStats(callback) {
} }
resolve(result); resolve(result);
}); });
procIoreg.on('error', function () {
if (callback) {
callback(result);
}
resolve(result);
});
} }
} else { } else {
result.ms = _fs_speed.last_ms; result.ms = _fs_speed.last_ms;

1
lib/index.d.ts vendored
View File

@ -123,6 +123,7 @@ export namespace Systeminformation {
buffers: number; buffers: number;
cached: number; cached: number;
slab: number; slab: number;
reclaimable: number;
swaptotal: number; swaptotal: number;
swapused: number; swapused: number;
swapfree: number; swapfree: number;

View File

@ -31,13 +31,13 @@ const _sunos = (_platform === 'sunos');
const RAM_manufacturers = { const RAM_manufacturers = {
'00CE': 'Samsung Electronics Inc', '00CE': 'Samsung Electronics Inc',
'014F': 'Transcend Information', '014F': 'Transcend Information Inc.',
'017A': 'Apacer Technology Inc', '017A': 'Apacer Technology Inc.',
'0198': 'HyperX', '0198': 'HyperX',
'029E': 'Corsair', '029E': 'Corsair',
'02FE': 'Elpida', '02FE': 'Elpida',
'04CB': 'A-DATA', '04CB': 'A-DATA',
'04CD': 'G-Skill International Enterprise', '04CD': 'G.Skill International Enterprise',
'059B': 'Crucial', '059B': 'Crucial',
'1315': 'Crucial', '1315': 'Crucial',
'2C00': 'Micron Technology Inc.', '2C00': 'Micron Technology Inc.',
@ -52,6 +52,7 @@ const RAM_manufacturers = {
'SAMSUNG': 'Samsung Electronics Inc.', 'SAMSUNG': 'Samsung Electronics Inc.',
'HYNIX': 'Hynix Semiconductor Inc.', 'HYNIX': 'Hynix Semiconductor Inc.',
'G-SKILL': 'G-Skill International Enterprise', 'G-SKILL': 'G-Skill International Enterprise',
'G.SKILL': 'G-Skill International Enterprise',
'TRANSCEND': 'Transcend Information', 'TRANSCEND': 'Transcend Information',
'APACER': 'Apacer Technology Inc', 'APACER': 'Apacer Technology Inc',
'MICRON': 'Micron Technology Inc.', 'MICRON': 'Micron Technology Inc.',
@ -151,6 +152,7 @@ function mem(callback) {
cached: 0, cached: 0,
slab: 0, slab: 0,
buffcache: 0, buffcache: 0,
reclaimable: 0,
swaptotal: 0, swaptotal: 0,
swapused: 0, swapused: 0,
@ -191,6 +193,8 @@ function mem(callback) {
result.writeback = result.writeback ? result.writeback * 1024 : 0; result.writeback = result.writeback ? result.writeback * 1024 : 0;
result.dirty = parseInt(util.getValue(lines, 'dirty'), 10); result.dirty = parseInt(util.getValue(lines, 'dirty'), 10);
result.dirty = result.dirty ? result.dirty * 1024 : 0; result.dirty = result.dirty ? result.dirty * 1024 : 0;
result.reclaimable = parseInt(util.getValue(lines, 'sreclaimable'), 10);
result.reclaimable = result.reclaimable ? result.reclaimable * 1024 : 0;
} }
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
@ -242,11 +246,11 @@ function mem(callback) {
util.noop(); util.noop();
} }
try { try {
exec('vm_stat 2>/dev/null | grep "Pages active"', function (error, stdout) { exec('vm_stat 2>/dev/null | egrep "Pages active|Pages inactive"', function (error, stdout) {
if (!error) { if (!error) {
let lines = stdout.toString().split('\n'); let lines = stdout.toString().split('\n');
result.active = (parseInt(util.getValue(lines, 'Pages active'), 10) || 0) * pageSize;
result.active = parseInt(lines[0].split(':')[1], 10) * pageSize; result.reclaimable = (parseInt(util.getValue(lines, 'Pages inactive'), 10) || 0) * pageSize;
result.buffcache = result.used - result.active; result.buffcache = result.used - result.active;
result.available = result.free + result.buffcache; result.available = result.free + result.buffcache;
} }