systeminformation
systeminformation copied to clipboard
100% CPU load on windows
Describe the bug Its not really a bug, more just something i noticed I m working on a monitoring tool using this library to get system data Therefore i need to get the data constantly On linux, this is no issue at all, but on windows, my cpu load goes up to 100%
To Reproduce
var data = {}
dataTransferInterval = setInterval(async () => {
data.cpu = await si.get({currentLoad:"currentLoad"})
data.ram = await si.get({mem:"total,used"})
data.disk = await si.get({fsSize:"size,used"})
}
}, 1000);
Current Output The output is fine, it just puts a LOT of load on the cpu on my windows system
Expected behavior Barely any noticable load on the cpu just like on my linux server
Environment (please complete the following information):
- systeminformation package version: 5.9.13
- Windows
- Asus ROG Gaming Laptop
Additional context Add any other context about the problem here.
@4n0nh4x0r thank you, yes this is something, we are doing an investigation. See also issue #616 ... hope to get a solution ready this weekend.
Hopefully something can be done, othetrwise my monitoring system will take 100% of the cpu power for itself alone on windows servers lol
Hello! I come to collaborate with this incident. I am developing a package of monitoring tools for servers and when testing version 5.9.7 it already had incidents with windows, I saw that I launch 5.9.14 and it persists. In my case, just checking any status flag (Timeup, CPU, OS) triggers the use of Powershell to 50% or more.
PS> Whoever wants to know my monitoring utility is called Healty https://github.com/gusgeek/Healty https://github.com/gusgeek/HealtyCenter For now in Spanish, soon in English.
@4n0nh4x0r ... I made detailed research and it turns out that spinning up PowerShell Process is responsible for consuming resource and time. I now created a possibility to create a persistent PowerShell which then should reduce resources by 90% ...
It would be great if you can test the latest code here on GitHub: What you have to do to enable the persistent power shell:
- on startup (if you are running in windows):
si.powerShellStart();
- and then again when shutting down the app:
si.powerShellRelease();
All commands In between will then use this already pinned up powerShell.
The implementation ist still a little hacky ... but if your results are fine and this is what you would like to use, I will make a clean up! Any comments are welcome!
Okay, that sounds fantastic actually For releasing the powershell again, does shutting down the app itself work aswell? or do i have to call powerShellRelease()?
I will test this once i m back at my dev pc
@4n0nh4x0r closing the app should also work but it would be cleaner to call powerShellRelease()
... the main thing for now is of course if this goes now into the right direction and solves the problem also on your side. If yes, I can make a cleanup and a new release. At least on my machines this was quite fast. So I hope this works also on your side ;-)
@sebhildebrandt getStaticData
doesnt work with the powerShellStart
i can see from process explorer
that node starts a single powershell and never opens more than one process,
HOWEVER the command also never finishes?
ALSO i can see the memory size of the powershell increases very dramatically and gets out of control 200MB!?
const si = require('systeminformation');
(async () => {
si.powerShellStart();
let abc = await si.getStaticData();
console.log(abc);
si.powerShellRelease();
})();
Awesome, it works for me No more cpu load shooting to 100%
As for the latest comment here on this thread, in my case this doesnt happen.
The powershell instance is being opened, and being worked with, and it stays constant on 40MB memory size
@4n0nh4x0r have you tried my simple script above? i see the single powershell open, then use about 60% cpu, usage and 200MB memory for about 20secs (as expected as its using a single powershell rather than loads) but then it doesnt output the response and the powershell also isnt released and node never quits?
For me it stays at stable low cpu usage, and the memory allocated to the powershell is at about 114MB in this case But other than that nothing special
For me it stays at stable low cpu usage, and the memory allocated to the powershell is at about 114MB in this case But other than that nothing special
do you get a reply though in the console and node quits?
I didnt get an output there, the script just continued doing work and never quits
I didnt get an output there, the script just continued doing work and never quits
so its not just me then, so something isnt right with the getStaticData
then and the powershell
also using your test script, the memory usage of powershell just keeps climbing for me? started at 34MB then starting climbing to 125MB after about 1 min running EDIT: running for 2 mins and its now at 130MB, defo memory leak
const si = require('systeminformation');
var data = {}
si.powerShellStart();
dataTransferInterval = setInterval(async () => {
data.cpu = await si.get({ currentLoad: "currentLoad" })
data.ram = await si.get({ mem: "total,used" })
data.disk = await si.get({ fsSize: "size,used" })
}, 1000);
@si458 Which version of nodejs are you using? I m using node 16(.11.1)
@si458 Which version of nodejs are you using? I m using node 16(.11.1)
Latest 14 LTS But I'm AFK at mo but will try updating to latest 16 LTS tomorrow and see what happens
Would be interesting to see if this is maybe a node version issue rather than a library issue itself
@si458 , @4n0nh4x0r thank you for your feedback! My feeling here is, that the issues you describes are not related to a specific node version. To sum up:
- my implementation is just a first step and I know that this is much to hacky!
- the intension was, that I can see that this might be an approach to get the resources under control.
- of course I need to have a look on it why we have a potential memory leak here.
- and I need to see why
getStaticData()
does not finish. Even if using just one Powershell instance it should complete... - then the next step is to extend this concept to use a (auto growing) shell pool for those who run a lot of commands
- I am thinking to implement something comparable to a connection pool for DBs with configurable time to live (in idle) and max pool size
All this is unfortunately needed because we HAVE to move to powershell and spinning up a powershell shell is so costly. I wish all of this would be as easy as with linux or Mac ;-)
@sebhildebrandt something to note
Cmd.exe isn't going away!
For example I can still run query user
to get all users,
Yet it was replaced with powershell?
Also I found no reference anywhere in the latest Windows 11 build that the wmic command line has indeed vanished?
@si458
USER: yes, you are right. The reason why it was replaced it due to international character problems. See also #610. The problem here is that windows keeps the original functionality and there is no way to get the stdout as UTF8 when executing query user
...
WMIC: yes it is marked as deprecated (https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmic) and I got reports that in some versions it was not longer available (I guess with Windows 11 22483 and higher it will be then completely removed) ... Generally wmic
has the same problem with international characters and this is also a reason why I had to move to powerShell ... I wish that this would be different but unfortunately this all is a little bit more complicated in windows.
@4n0nh4x0r i have just tried upgrading my node to 16.13.0 and its the same issue runs one instance of powershell as expected, but the memory usage of it keeps climbing, ok its very very slowly but it still climbs @sebhildebrandt maybe you need to clear the old data from the console window after so long? i also understand these things take time but baby steps in the right direction 👍
@4n0nh4x0r after me watching process explorer
using only data.cpu = await si.get({ currentLoad: "currentLoad" })
doesnt see a memory increase?
but if you use only data.ram = await si.get({ mem: "total,used" })
or data.disk = await si.get({ fsSize: "size,used" })
then suddenly the memory increases in the powershell instance?
@sebhildebrandt might be helpful to debug maybe
in this way, with promise all I managed to obtain data from all sides without exploiting the use of cpu
let search = new Object() Promise.all(
[
"os",
"disk",
"cpuload",
"networkstate",
"networkconnections",
"networkdevices",
"ram",
"uptime"
].map(async item => {
switch (item) {
case "os":
await si.osInfo().then(data => { search.os = data })
.catch((e)=>{ loggering('app', JSON.stringify(e) , path.join(deployPath, 'log/') ) })
break;
case "disk":
await si.fsSize().then(data => { search.disk = data })
.catch((e)=>{ loggering('app', JSON.stringify(e) , path.join(deployPath, 'log/') ) })
break;
case "cpuload":
await si.currentLoad().then(data => { search.cpuload = data })
.catch((e)=>{ loggering('app', JSON.stringify(e) , path.join(deployPath, 'log/') ) })
break;
case "networkstate":
await si.networkConnections().then(data => {
let establecido = 0, escuchando = 0, esperando_cierre = 0, time_wait = 0, cerrado = 0, UNKNOWN = 0, SYN_SENT = 0, SYN_RECV = 0, LAST_ACK = 0, FIN_WAIT1 = 0, FIN_WAIT2 = 0
for (let index = 0; index < data.length; index++) {
const element = data[index].state;
switch (data[index].state) {
case "ESTABLISHED":
establecido ++
break;
case "CLOSE":
cerrado ++
break;
case "TIME_WAIT":
time_wait ++
break;
case "LISTEN":
escuchando ++
break;
case "CLOSE_WAIT":
esperando_cierre ++
break;
case "SYN_SENT":
SYN_SENT ++
break;
case "SYN_RECV":
SYN_RECV ++
break;
case "LAST_ACK":
LAST_ACK ++
break;
case "FIN_WAIT1":
FIN_WAIT1 ++
break;
case "FIN_WAIT2":
FIN_WAIT2 ++
break;
default:
UNKNOWN ++
break;
}
}
search.networkstate = {
ESTABLISHED: establecido,
CLOSE: cerrado,
TIME_WAIT: time_wait,
LISTEN: escuchando,
CLOSE_WAIT:esperando_cierre,
UNKNOWN: UNKNOWN,
SYN_SENT:SYN_SENT,
SYN_RECV:SYN_RECV,
LAST_ACK:LAST_ACK,
FIN_WAIT1:FIN_WAIT1,
FIN_WAIT2:FIN_WAIT2
}
})
.catch((e)=>{ loggering('app', JSON.stringify(e) , path.join(deployPath, 'log/') ) })
break;
case "networkconnections":
await si.networkConnections().then(data => { search.networkconnections = data })
.catch((e)=>{ loggering('app', JSON.stringify(e) , path.join(deployPath, 'log/') ) })
break;
case "networkdevices":
await si.networkStats().then(data => { search.networkdevices = data })
.catch((e)=>{ loggering('app', JSON.stringify(e) , path.join(deployPath, 'log/') ) })
break;
case "processes":
await si.processes().then(data => { search.processes = data })
.catch((e)=>{ loggering('app', JSON.stringify(e) , path.join(deployPath, 'log/') ) })
break;
case "ram":
await si.mem().then(data => { search.ram = data })
.catch((e)=>{ loggering('app', JSON.stringify(e) , path.join(deployPath, 'log/') ) })
break;
case "uptime":
let totalSeconds = si.time().uptime;
let seconds = parseInt(totalSeconds, 10);
let days = Math.floor(seconds / (3600*24));
seconds -= days*3600*24;
let hrs = Math.floor(seconds / 3600);
seconds -= hrs*3600;
let mnts = Math.floor(seconds / 60);
seconds -= mnts*60;
search.uptime = {
"dias": days,
"horas": hrs,
"minutos": mnts,
"segundos": seconds
}
break;
}}
)