简体   繁体   English

通过 NodeJS 获取/查看 Memory 和 CPU 使用率

[英]Get/View Memory & CPU usage via NodeJS

I see there are several node packages that allow you to look up a specific process's usage, such as https://www.npmjs.com/package/usage我看到有几个节点包可以让你查找特定进程的使用情况,例如https://www.npmjs.com/package/usage

I am trying to get the overall sever usage/stats (CPU and Memory), not just one specific process or another.我正在尝试获取总体服务器使用情况/统计信息(CPU 和内存),而不仅仅是一个特定的进程或另一个。 Maybe even disk space usage.甚至磁盘空间使用情况。

I am currently unable to find anything like this, is this possible?我目前找不到这样的东西,这可能吗?

The native module os can give you some memory and cpu usage statistics.本机模块os可以为您提供一些内存和 cpu 使用情况统计信息。

var os = require('os');

console.log(os.cpus());
console.log(os.totalmem());
console.log(os.freemem())

The cpus() function gives you an average, but you can calculate the current usage by using a formula and an interval, as mentioned in this answer. cpus() 函数为您提供平均值,但您可以使用公式和间隔来计算当前使用情况,如答案中所述。

There is also a package that does this for you, called os-utils .还有一个包可以为您执行此操作,称为os-utils

Taken from the example on github:取自github上的示例:

var os = require('os-utils');

os.cpuUsage(function(v){
    console.log( 'CPU Usage (%): ' + v );
});

For information about the disk you can use diskspace有关磁盘的信息,您可以使用diskspace

Check node-os-utils检查node-os-utils

  • CPU average usage CPU平均使用率
  • Free and used drive space可用和已用驱动器空间
  • Free and used memory space可用和已用内存空间
  • Operating System操作系统
  • All processes running正在运行的所有进程
  • TTY/SSH opened TTY/SSH 打开
  • Total opened files打开的文件总数
  • Network speed (input and output)网络速度(输入和输出)
 var osu = require('node-os-utils') var cpu = osu.cpu cpu.usage() .then(info => { console.log(info) })

As I found no code to solve this problem and don't want to rely on other packages just for some lines of code, I wrote a function that calculates the average CPU load between two successive function calls.由于我找不到解决此问题的代码,并且不想仅仅为了某些代码行而依赖其他包,因此我编写了一个 function 来计算两个连续的 function 调用之间的平均 CPU 负载。 I am assuming t_idle + t_user + t_sys = total cpu time and results are kind of similar to the ones of my Windows task manager, however, the usage seems little more sensitive to me (eg music playback increases the cpu load more than in the Windows task manager).我假设t_idle + t_user + t_sys = total cpu time and results are kind of similar to the ones of my Windows task manager, however, usage seems small more sensitive to me (eg music playback increases cpu load more than in the Windows任务管理器)。 Please corret me if my assumptions are wrong.如果我的假设是错误的,请纠正我。

const os = require('os');

// Initial value; wait at little amount of time before making a measurement.
let timesBefore = os.cpus().map(c => c.times);

// Call this function periodically e.g. using setInterval, 
function getAverageUsage() {
    let timesAfter = os.cpus().map(c => c.times);
    let timeDeltas = timesAfter.map((t, i) => ({
        user: t.user - timesBefore[i].user,
        sys: t.sys - timesBefore[i].sys,
        idle: t.idle - timesBefore[i].idle
    }));

    timesBefore = timesAfter;

    return timeDeltas
        .map(times => 1 - times.idle / (times.user + times.sys + times.idle))
        .reduce((l1, l2) => l1 + l2) / timeDeltas.length;
}

You can also use process.cpuUsage() to return the system and user cpu time in microseconds.您还可以使用process.cpuUsage()以微秒为单位返回系统和用户 cpu 时间。 It can also calculate the difference to a previous call.它还可以计算与先前调用的差异。

https://nodejs.org/api/process.html#process_process_cpuusage_previousvalue https://nodejs.org/api/process.html#process_process_cpuusage_previousvalue

Node.js has os.loadavg() method Node.js 有os.loadavg()方法

// Require os module
const os = require('os');

// Printing os.loadavg() value
var avg_load = os.loadavg();

console.log("Load average (1 minute):"
            + String(avg_load[0]));

console.log("Load average (5 minute):"
            + String(avg_load[1]));

console.log("Load average (15 minute):"
            + String(avg_load[2]));

More info here更多信息在这里

async function getinfo() {
 const cpu = await si.cpu();
 const disk = (await si.diskLayout())[0];
 const os = await si.osInfo();
 const versions = await si.versions();
 const ram = await si.mem();

 // CPU Info
 let info = `CPU: ${cpu.manufacturer} ${cpu.brand} ${cpu.speed}GHz\n`;
 info += `Cores: ${cpu.cores} (${cpu.physicalCores} Physical)\n`;

 // RAM Info
 const totalRam = Math.round(ram.total / 1024 / 1024 / 1024);
 info += `RAM: ${totalRam}GB\n`;

 // Disk Info
 const size = Math.round(disk.size / 1024 / 1024 / 1024);
 info += `Disk: ${disk.vendor} ${disk.name} ${size}GB ${disk.type} (${disk.interfaceType})\n`;

 //OS Info
 info += `OS: ${os.distro} ${os.codename} (${os.platform})\n`;
 info += `Kernel: ${os.kernel} ${os.arch}\n`;

 // Node Info
 info += `Node: v${versions.node}\n`;
 info += `V8: ${versions.v8}`;
 return info;
}

Of course it is possible.当然这是可能的。 But you'll need a C++ native module to do that.但是您需要一个 C++ 本机模块来做到这一点。 And keep in mind that every OS has their own way of querying system resource usage.请记住,每个操作系统都有自己的查询系统资源使用情况的方式。

For example, if you're on Windows (which might be what you're looking for since usage doesn't support Windows), you could do something like例如,如果你在 Windows 上(这可能是你正在寻找的,因为usage不支持 Windows),你可以做类似的事情

performance.cpp性能.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性能算法.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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM