#include "qgapplicationperformance.h" #include #include #include #include #include #include static QgApplicationPerformance* globalInstance; struct MyCounters { unsigned long refresh_rate; float cpu; float cpu_peek; float mem; float mem_peek; uint64_t kt; uint64_t ut; uint64_t tt; unsigned int cores; int tid; unsigned long long net_bytes; unsigned long long net_bytes_period; float net_band; unsigned net_index; QString hAddress; bool calculate(QElapsedTimer& t); //unsigned long period_ms); }; static MyCounters myCounters; QgApplicationPerformance::QgApplicationPerformance(QObject *parent) : QObject(parent) { myCounters.refresh_rate=2; net_index=0; myCounters.net_index=0; } QgApplicationPerformance& QgApplicationPerformance::instance() { if (!globalInstance) { globalInstance=new QgApplicationPerformance; myCounters.tid=0; //globalInstance->startTimer(myCounters.refresh_rate*1000, Qt::PreciseTimer); myCounters.ut=0; myCounters.kt=0; myCounters.tt=0; myCounters.cores=1; SYSTEM_INFO sysInfo; GetSystemInfo(&sysInfo); myCounters.cores=sysInfo.dwNumberOfProcessors>0 ? sysInfo.dwNumberOfProcessors : 1; globalInstance->setRefreshRate(2); myCounters.calculate(globalInstance->elapsedTimer); globalInstance->elapsedTimer.start(); } return *globalInstance; } void QgApplicationPerformance::timerEvent(QTimerEvent* evn) { if (evn->timerId()==myCounters.tid) { //qint64 elapsed=elapsedTimer.elapsed(); if (myCounters.calculate(elapsedTimer)) //myCounters.refresh_rate*1000)) Q_EMIT countersUpdated(); evn->accept(); } else QObject::timerEvent(evn); } void QgApplicationPerformance::setRefreshRate(unsigned long seconds) { myCounters.refresh_rate=seconds; if (myCounters.tid) { killTimer(myCounters.tid); myCounters.tid=0; } myCounters.tid=globalInstance->startTimer(myCounters.refresh_rate*1000); } void QgApplicationPerformance::setNetworkInterfaceIndex(unsigned int index, const QString& hAddress) { myCounters.net_index=index; myCounters.hAddress=hAddress; } void QgApplicationPerformance::reset() { if (myCounters.tid) killTimer(myCounters.tid); myCounters.tid=0; elapsedTimer.invalidate(); myCounters.ut=0; myCounters.kt=0; myCounters.tt=0; myCounters.mem_peek=0; myCounters.cpu_peek=0; myCounters.mem=0; myCounters.cpu=0; myCounters.net_band=0; myCounters.net_bytes=0; myCounters.net_bytes_period=0; myCounters.calculate(elapsedTimer); setRefreshRate(myCounters.refresh_rate); } unsigned long QgApplicationPerformance::refreshRate() const { return myCounters.refresh_rate; } unsigned int QgApplicationPerformance::cpuUsage() const { return myCounters.cpu; } unsigned int QgApplicationPerformance::peekCpuUsage() const { return myCounters.cpu_peek; } unsigned long QgApplicationPerformance::memoryUsageKiB() const { return myCounters.mem/1024; } unsigned long QgApplicationPerformance::peekMemoryUsageKiB() const { return myCounters.mem_peek/1024; } QString QgApplicationPerformance::toString() { return QString("%1%(%2%), %3MB/%4MB, N: %5%(%6KB) @%7") .arg(cpuUsage()).arg(peekCpuUsage()).arg(memoryUsageKiB()/1000).arg(peekMemoryUsageKiB()/1000) .arg(myCounters.net_band, 0, 'f', 2).arg(myCounters.net_bytes_period).arg(myCounters.hAddress); } void QgApplicationPerformance::updateCounters() { } // static unsigned long long GetMemoryUsage() { PROCESS_MEMORY_COUNTERS_EX memInfo; memInfo.cb=sizeof memInfo; auto ok=GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&memInfo, sizeof memInfo); if (ok) { return memInfo.PrivateUsage; //WorkingSetSize; } return 0; } static bool GetNetworkLoad(unsigned int index, unsigned long long &bytes, unsigned long long &speed); bool MyCounters::calculate(QElapsedTimer & timer) { auto m=GetMemoryUsage(); if (m>myCounters.mem_peek) myCounters.mem_peek=m; myCounters.mem=m; FILETIME pct; FILETIME pext; FILETIME pkt; FILETIME put; auto period_ms=timer.isValid() ? timer.elapsed() : 0; auto ok=GetProcessTimes(GetCurrentProcess(), &pct, &pext, &pkt, &put); if (ok) { timer.start(); uint64_t k=pkt.dwHighDateTime; k=k<<32; k|=uint64_t(pkt.dwLowDateTime); uint64_t u=put.dwHighDateTime; u=u<<32; u|=uint64_t(put.dwLowDateTime); if (period_ms) { uint64_t period_us=period_ms; period_us=period_us*10; uint64_t dk=k-myCounters.kt; uint64_t du=u-myCounters.ut; //From 100ns to us dk=dk/10; du=du/10; uint64_t tot_us=dk+du; double cpu_usage=(double(tot_us)/double(period_us))/cores; myCounters.cpu=(cpu_usage+0.5); if (myCounters.cpu>cpu_peek) myCounters.cpu_peek=myCounters.cpu; } kt=k; ut=u; //return true; } if (net_index) { unsigned long long bytes; unsigned long long speed; if (!GetNetworkLoad(net_index, bytes, speed)) return true; if (speed>0) { if (period_ms) { float seconds=float(period_ms)*0.001; unsigned long long d=bytes-net_bytes; //float ds=d*float(period_ms*10000); net_bytes_period=(d/seconds)/1000; //ds/(period_ms*10000); if (speed) { float s=(float(speed)/8)*seconds; float b=d/s; b=b*100; net_band=b; } } net_bytes=bytes; //net_band=0; } } return true; } #include #if 0 struct myiftable_t{ DWORD dwNumEntries; MIB_IFROW table[42]; }; static myiftable_t static_iftab; static MIB_IFTABLE* iftab; #endif static MIB_IFROW* ifrow; static MIB_IFROW saved_ifrow; static bool net_info_error; static bool GetNetworkLoad(unsigned int index, unsigned long long& bytes, unsigned long long &speed) { bytes=0; speed=1; if (net_info_error) return false; #if 0 if (!ifrow) { DWORD dwSize=sizeof static_iftab; iftab=(MIB_IFTABLE*)&static_iftab; DWORD r=GetIfTable(iftab, &dwSize, 0); if (r==ERROR_INSUFFICIENT_BUFFER) { iftab=(MIB_IFTABLE*)new char[dwSize+100]; memset(iftab, dwSize, 0); r=GetIfTable(iftab, &dwSize, 0); } if (r!=NO_ERROR) { net_info_error=true; return false; } saved_ifrow.dwIndex=iftab->table[20].dwIndex; qDebug()<<"Perf-mon: ETH"<dwInOctets+ifrow->dwOutOctets; bytes=total; speed=ifrow->dwSpeed; return true; }