Получение/просмотр использования памяти и процессора через NodeJS
Я вижу, что есть несколько пакетов узлов, которые позволяют вам искать конкретное использование процесса, например https://www.npmjs.com/package/usage.
Я пытаюсь получить общий уровень использования/статистику (CPU и Memory), а не только один конкретный процесс. Возможно, даже использование дискового пространства.
В настоящее время я не могу найти что-либо подобное, возможно ли это?
Ответы
Ответ 1
Нативный модуль os может предоставить вам некоторую статистику использования памяти и процессора.
var os = require('os');
console.log(os.cpus());
console.log(os.totalmem());
console.log(os.freemem())
Функция cpus() дает вам среднее значение, но вы можете рассчитать текущее использование, используя формулу и интервал, как указано в этом ответе.
Существует также пакет, который делает это для вас, называется os-utils.
Взято из примера на github:
var os = require('os-utils');
os.cpuUsage(function(v){
console.log( 'CPU Usage (%): ' + v );
});
Для получения информации о диске вы можете использовать дисковое пространство
Ответ 2
Проверьте node-os-utils
- Среднее использование процессора
- Свободное и использованное дисковое пространство
- Свободное и использованное пространство памяти
- Операционная система
- Все процессы запущены
- TTY/SSH открыт
- Всего открытых файлов
- Скорость сети (вход и выход)
var osu = require('node-os-utils')
var cpu = osu.cpu
cpu.usage()
.then(info => {
console.log(info)
})
Ответ 3
Это полнофункциональное решение с множеством полезных опций.
https://www.npmjs.com/package/systeminformation
Ответ 4
Вы также можете использовать process.cpuUsage()
для возврата системного и пользовательского времени процессора в микросекундах. Он также может рассчитать разницу до предыдущего вызова.
https://nodejs.org/api/process.html#process_process_cpuusage_previousvalue
Ответ 5
Конечно, это возможно. Но для этого вам понадобится собственный модуль C++. И имейте в виду, что каждая ОС имеет свой собственный способ запроса на использование системных ресурсов.
Например, если вы работаете в Windows (это может быть то, что вы ищете, поскольку usage
не поддерживает Windows), вы можете сделать что-то вроде
performance.cpp
#include <node.h>
#include "performance_algorithm.hpp"
using namespace v8;
void InitAll(Handle<Object> exports) {
PerformanceAlgorithm::Initialize();
PerformanceAlgorithm::RegisterMethod(exports);
}
NODE_MODULE(Performance, InitAll)
performance_algorithm.cpp
#include <algorithm>
#include "baton.hpp"
#include "structs.hpp"
#include "performance_algorithm.hpp"
void PerformanceAlgorithm::Initialize() {
PdhOpenQuery(NULL, NULL, &cpuQuery);
PdhAddCounter(cpuQuery, "\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
PdhCollectQueryData(cpuQuery);
}
void PerformanceAlgorithm::RegisterMethod(Handle<Object> exports) {
NODE_SET_METHOD(exports, "getPerformanceData", PerformanceAlgorithm::GetPerformanceDataAsync);
}
void PerformanceAlgorithm::GetPerformanceDataAsync(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
if (args.Length() != 1) {
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
} else {
if (!args[0]->IsFunction()) {
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong arguments type")));
} else {
Local<Function> callbackFunction = Local<Function>::Cast(args[0]);
Baton<string, PerformanceData>* baton = new Baton<string, PerformanceData>();
baton->request.data = baton;
baton->callbackFunction.Reset(isolate, callbackFunction);
uv_queue_work(uv_default_loop(), &baton->request, PerformanceAlgorithm::GetPerformanceDataWork, PerformanceAlgorithm::GetPerformanceDataAsyncAfter);
}
}
}
void PerformanceAlgorithm::GetPerformanceDataWork(uv_work_t* request) {
Baton<string, PerformanceData>* baton = static_cast<Baton<string, PerformanceData>*>(request->data);
baton->result.memory_info.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&baton->result.memory_info);
PDH_FMT_COUNTERVALUE counterVal;
PdhCollectQueryData(cpuQuery);
PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
baton->result.cpu_usage = counterVal.doubleValue;
DWORD processIDs[1024], bytesReturned;
EnumProcesses(processIDs, sizeof(processIDs), &bytesReturned);
DWORD numberOfProcesses = bytesReturned / sizeof(DWORD);
for (int i = 0; i < numberOfProcesses; i++) {
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]);
HMODULE hMods[1024];
DWORD cbNeeded;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
for (int j = 0; j < (cbNeeded / sizeof(HMODULE)); j++) {
TCHAR szModName[MAX_PATH];
GetModuleFileNameEx(hProcess, hMods[j], szModName, sizeof(szModName) / sizeof(TCHAR));
ProcessInfo info;
info.process_id = processIDs[i];
info.path = string(szModName);
baton->result.processes.push_back(info);
break;
}
}
CloseHandle(hProcess);
}
sort(baton->result.processes.begin(), baton->result.processes.end(), [](ProcessInfo a, ProcessInfo b) -> bool {
return a.process_id < b.process_id;
});
GetPerformanceInfo(&baton->result.performance_info, sizeof(PERFORMACE_INFORMATION));
}
void PerformanceAlgorithm::GetPerformanceDataAsyncAfter(uv_work_t* request, int status) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
EscapableHandleScope escapableHandleScope(isolate);
Baton<string, PerformanceData>* baton = static_cast<Baton<string, PerformanceData>*>(request->data);
Local<Function> callbackFunction = Local<Function>::New(isolate, baton->callbackFunction);
Local<Object> returnValue = Object::New(isolate);
returnValue->Set(String::NewFromUtf8(isolate, "cpu_usage"), Number::New(isolate, baton->result.cpu_usage));
returnValue->Set(String::NewFromUtf8(isolate, "ram_usage"), Number::New(isolate, baton->result.memory_info.dwMemoryLoad));
returnValue->Set(String::NewFromUtf8(isolate, "total_physical_memory"), Number::New(isolate, baton->result.memory_info.ullTotalPhys));
returnValue->Set(String::NewFromUtf8(isolate, "available_physical_memory"), Number::New(isolate, baton->result.memory_info.ullAvailPhys));
returnValue->Set(String::NewFromUtf8(isolate, "total_page_file"), Number::New(isolate, baton->result.memory_info.ullTotalPageFile));
returnValue->Set(String::NewFromUtf8(isolate, "available_page_file"), Number::New(isolate, baton->result.memory_info.ullAvailPageFile));
returnValue->Set(String::NewFromUtf8(isolate, "total_virtual"), Number::New(isolate, baton->result.memory_info.ullTotalVirtual));
returnValue->Set(String::NewFromUtf8(isolate, "available_virtual"), Number::New(isolate, baton->result.memory_info.ullAvailVirtual));
Local<Array> processes = Array::New(isolate, baton->result.processes.size());
for (int i = 0; i < baton->result.processes.size(); i++) {
Local<Object> processInfo = Object::New(isolate);
processInfo->Set(String::NewFromUtf8(isolate, "process_id"), Number::New(isolate, baton->result.processes[i].process_id));
processInfo->Set(String::NewFromUtf8(isolate, "path"), String::NewFromUtf8(isolate, baton->result.processes[i].path.c_str()));
processes->Set(i, processInfo);
}
returnValue->Set(String::NewFromUtf8(isolate, "running_processes"), processes);
const unsigned int argc = 1;
Handle<Value> argv[argc] = { escapableHandleScope.Escape(returnValue) };
callbackFunction->Call(isolate->GetCurrentContext()->Global(), argc, argv);
baton->callbackFunction.Reset();
delete baton;
}