簡體   English   中英

通過 NodeJS 獲取/查看 Memory 和 CPU 使用率

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

我看到有幾個節點包可以讓你查找特定進程的使用情況,例如https://www.npmjs.com/package/usage

我正在嘗試獲取總體服務器使用情況/統計信息(CPU 和內存),而不僅僅是一個特定的進程或另一個。 甚至磁盤空間使用情況。

我目前找不到這樣的東西,這可能嗎?

本機模塊os可以為您提供一些內存和 cpu 使用情況統計信息。

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 );
});

有關磁盤的信息,您可以使用diskspace

檢查node-os-utils

  • CPU平均使用率
  • 可用和已用驅動器空間
  • 可用和已用內存空間
  • 操作系統
  • 正在運行的所有進程
  • TTY/SSH 打開
  • 打開的文件總數
  • 網絡速度(輸入和輸出)
 var osu = require('node-os-utils') var cpu = osu.cpu cpu.usage() .then(info => { console.log(info) })

由於我找不到解決此問題的代碼,並且不想僅僅為了某些代碼行而依賴其他包,因此我編寫了一個 function 來計算兩個連續的 function 調用之間的平均 CPU 負載。 我假設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任務管理器)。 如果我的假設是錯誤的,請糾正我。

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;
}

您還可以使用process.cpuUsage()以微秒為單位返回系統和用戶 cpu 時間。 它還可以計算與先前調用的差異。

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

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]));

更多信息在這里

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;
}

當然這是可能的。 但是您需要一個 C++ 本機模塊來做到這一點。 請記住,每個操作系統都有自己的查詢系統資源使用情況的方式。

例如,如果你在 Windows 上(這可能是你正在尋找的,因為usage不支持 Windows),你可以做類似的事情

性能.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)

性能算法.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