From ed1a89508a0523609cd66b57ae9feae8485f16d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Wed, 21 Jun 2017 14:00:45 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/pip@513 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5 --- src_main/system/pisysteminfo.h | 2 +- src_main/system/pisystemmonitor.cpp | 71 ++++++++++++++++++++++++++++- src_main/system/pisystemmonitor.h | 43 +++++++++++++++-- src_main/thread/pithread.cpp | 70 ++++++++++++++++++++++++++++ src_main/thread/pithread.h | 32 ++++++++++++- utils/system_daemon/daemon.cpp | 8 ++++ utils/system_daemon/main.cpp | 45 ++++++++++++++---- 7 files changed, 253 insertions(+), 18 deletions(-) diff --git a/src_main/system/pisysteminfo.h b/src_main/system/pisysteminfo.h index cbcc2ac4..bdd0c2c6 100644 --- a/src_main/system/pisysteminfo.h +++ b/src_main/system/pisysteminfo.h @@ -36,7 +36,7 @@ public: ullong space_used; ullong space_free; }; - + PIString ifconfigPath, execCommand, hostname, user, OS_name, OS_version, architecture; PIDateTime execDateTime; int processorsCount; diff --git a/src_main/system/pisystemmonitor.cpp b/src_main/system/pisystemmonitor.cpp index b2ea524e..c171a7bd 100755 --- a/src_main/system/pisystemmonitor.cpp +++ b/src_main/system/pisystemmonitor.cpp @@ -20,6 +20,7 @@ #include "piincludes_p.h" #include "pisystemmonitor.h" #include "pisysteminfo.h" +#include "piprocess.h" #include "pitime_win.h" #ifdef WINDOWS # include @@ -40,6 +41,7 @@ PRIVATE_DEFINITION_END(PISystemMonitor) PISystemMonitor::PISystemMonitor(): PIThread() { + self_ = false; pID_ = cycle = 0; cpu_count = PISystemInfo::instance()->processorsCount; #ifndef WINDOWS @@ -68,8 +70,9 @@ PISystemMonitor::ProcessStats::ProcessStats() { } -bool PISystemMonitor::startOnProcess(int pID) { +bool PISystemMonitor::startOnProcess(int pID, int interval_ms) { stop(); + self_ = false; pID_ = pID; #ifndef WINDOWS file.open("/proc/" + PIString::fromNumber(pID_) + "/stat", PIIODevice::ReadOnly); @@ -87,7 +90,22 @@ bool PISystemMonitor::startOnProcess(int pID) { } PRIVATE->tm.reset(); #endif - return start(1000); + return start(interval_ms); +} + + +bool PISystemMonitor::startOnSelf(int interval_ms) { + bool ret = startOnProcess(PIProcess::currentPID(), interval_ms); + self_ = true; + return ret; +} + + +PIVector PISystemMonitor::threadsStatistic() const { + mutex_.lock(); + PIVector ret = cur_tm.values(); + mutex_.unlock(); + return ret; } @@ -206,6 +224,21 @@ void PISystemMonitor::run() { stat.cpu_load_system = piClampf(stat.cpu_load_system, 0.f, 100.f); stat.cpu_load_user = piClampf(stat.cpu_load_user, 0.f, 100.f); + + last_tm = cur_tm; + gatherThreadsStats(); + //PISystemTime dt = PISystemTime::fromMilliseconds(delay_); + for (PIMap::iterator i = cur_tm.begin(); i != cur_tm.end(); ++i) { + if (!last_tm.contains(i.key())) continue; + ThreadStats & ts_new(i.value()); + ThreadStats & ts_old(last_tm[i.key()]); + ts_new.cpu_load_kernel = calcThreadUsage(ts_new.kernel_time, ts_old.kernel_time); + ts_new.cpu_load_user = calcThreadUsage(ts_new.user_time, ts_old.user_time); + } + lock(); + cur_ts = cur_tm.values(); + unlock(); + makeStrings(); } @@ -217,3 +250,37 @@ void PISystemMonitor::makeStrings() { stat.virtual_memsize_readable.setReadableSize(stat.virtual_memsize); stat.data_memsize_readable.setReadableSize(stat.data_memsize); } + + +void PISystemMonitor::gatherThreadsStats() { + cur_ts.clear(); + cur_tm.clear(); + if (!self_) return; + __PIThreadCollection * pitc = __PIThreadCollection::instance(); + pitc->lock(); + PIVector tv = pitc->threads(); + piForeachC (PIThread * t, tv) { + ThreadStats ts; + ts.name = t->name(); +#ifdef WINDOWS + FILETIME times[4]; + PISystemTime ct = PISystemTime::current(); + if (GetThreadTimes(t->handle(), &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) { + piCout << "[PISystemMonitor] threadsInfo():: GetThreadTimes() error:" << errorString(); + continue; + } + ts.created = FILETIME2PIDateTime(times[0]); + ts.work_time = ct - ts.created.toSystemTime(); + ts.kernel_time = FILETIME2PISystemTime(times[2]); + ts.user_time = FILETIME2PISystemTime(times[3]); +#endif + cur_ts << ts; + cur_tm[t] = ts; + } + pitc->unlock(); +} + + +float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old) { + if (delay_ <= 0) return -1.; + return piClampf(100. * ((t_new - t_old).toMilliseconds() / delay_), 0.f, 100.f);} diff --git a/src_main/system/pisystemmonitor.h b/src_main/system/pisystemmonitor.h index 24feff18..5ccbfc31 100755 --- a/src_main/system/pisystemmonitor.h +++ b/src_main/system/pisystemmonitor.h @@ -21,7 +21,7 @@ #define PISYSTEMMONITOR_H #include "pithread.h" -#include "piprocess.h" +#include "pifile.h" class PIP_EXPORT PISystemMonitor: public PIThread { @@ -53,23 +53,58 @@ public: float cpu_load_system; float cpu_load_user; }; + struct ThreadStats { + ThreadStats() {cpu_load_kernel = cpu_load_user = -1.f;} + PIString name; + PIDateTime created; + PISystemTime work_time; + PISystemTime kernel_time; + PISystemTime user_time; + float cpu_load_kernel; + float cpu_load_user; + /*PIString device; + PIString filesystem; + PIString label; + ullong space_all; + ullong space_used; + ullong space_free;*/ + }; - bool startOnProcess(int pID); - bool startOnSelf() {return startOnProcess(PIProcess::currentPID());} + bool startOnProcess(int pID, int interval_ms = 1000); + bool startOnSelf(int interval_ms = 1000); + void stop(); const ProcessStats & statistic() const {return stat;} + PIVector threadsStatistic() const; void setStatistic(const ProcessStats & s) {stat = s; makeStrings();} private: - void stop(); void run(); void makeStrings(); + void gatherThreadsStats(); + float calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old); PIFile file, filem; ProcessStats stat; + PIVector cur_ts; + PIMap last_tm, cur_tm; + bool self_; int pID_, page_size, cpu_count, cycle; PRIVATE_DECLARATION }; +inline PICout operator <<(PICout s, const PISystemMonitor::ThreadStats & v) { + s.setControl(0, true); + s << "ThreadInfo(\"" << v.name << "\", created " << v.created + << ", work " << v.work_time.toMilliseconds() << " ms" + << ", kernel " << v.kernel_time.toMilliseconds() << " ms" + << ", user " << v.user_time.toMilliseconds() << " ms" + /*<< ", label \"" << v.label << "\", all " << PIString::readableSize(v.space_all) + << ", used " << PIString::readableSize(v.space_used) + << ", free " << PIString::readableSize(v.space_free)*/ << ")\n"; + s.restoreControl(); + return s; +} + #endif // PISYSTEMMONITOR_H diff --git a/src_main/thread/pithread.cpp b/src_main/thread/pithread.cpp index 744ab154..502418f3 100755 --- a/src_main/thread/pithread.cpp +++ b/src_main/thread/pithread.cpp @@ -33,6 +33,8 @@ __THREAD_FUNC_RET__ thread_function(void * t) {PIThread::__thread_func__(t); return 0;} __THREAD_FUNC_RET__ thread_function_once(void * t) {PIThread::__thread_func_once__(t); return 0;} +#define REGISTER_THREAD(t) __PIThreadCollection::instance()->registerThread(t) +#define UNREGISTER_THREAD(t) __PIThreadCollection::instance()->unregisterThread(t) /*! \class PIThread * \brief Thread class @@ -84,6 +86,64 @@ end(); */ + + +__PIThreadCollection *__PIThreadCollection::instance() { + /*static CDCore * ret = new CDCore(); + return ret;*/ + return __PIThreadCollection_Initializer__::__instance__; +} + + +void __PIThreadCollection::registerThread(PIThread * t) { + lock(); + if (!threads_.contains(t)) + threads_ << t; + unlock(); +} + + +void __PIThreadCollection::unregisterThread(PIThread * t) { + lock(); + threads_.removeAll(t); + unlock(); +} + + +PIVector __PIThreadCollection::threads() const { + return threads_; +} + + + + +int __PIThreadCollection_Initializer__::count_(0); +__PIThreadCollection * __PIThreadCollection_Initializer__::__instance__(0); + + +__PIThreadCollection_Initializer__::__PIThreadCollection_Initializer__() { + count_++; + //piCout << "try create Core" << count_; + if (count_ > 1) return; + //piCout << "create Core"; + __instance__ = new __PIThreadCollection(); +} + + +__PIThreadCollection_Initializer__::~__PIThreadCollection_Initializer__() { + count_--; + //piCout << "try delete Core" << count_; + if (count_ > 0) return; + //piCout << "delete Core"; + if (__instance__ != 0) { + delete __instance__; + __instance__ = 0; + } +} + + + + PRIVATE_DEFINITION_START(PIThread) #ifndef WINDOWS pthread_t thread; @@ -211,6 +271,7 @@ bool PIThread::startOnce() { void PIThread::terminate() { if (PRIVATE->thread == 0) return; + REGISTER_THREAD(this); PIINTROSPECTION_UNREGISTER_THREAD(tid()); terminating = running_ = false; tid_ = -1; @@ -285,6 +346,11 @@ void PIThread::setPriority(PIThread::Priority prior) { } +void * PIThread::handle() const { + return PRIVATE->thread; +} + + bool PIThread::waitForFinish(int timeout_msecs) { if (!running_) return true; if (timeout_msecs < 0) { @@ -327,6 +393,7 @@ void PIThread::__thread_func__(void * t) { ct.tid_ = GetCurrentThreadId(); #endif PIINTROSPECTION_REGISTER_THREAD(ct.tid(), ct.priority(), ct.name()); + REGISTER_THREAD(&ct); ct.running_ = true; if (ct.lockRun) ct.mutex_.lock(); ct.begin(); @@ -368,6 +435,7 @@ void PIThread::__thread_func__(void * t) { ct.tid_ = -1; //cout << "thread " << t << " exiting ... " << endl; //piCout << "pthread_exit" << (ct.__privateinitializer__.p)->thread; + UNREGISTER_THREAD(&ct); PIINTROSPECTION_UNREGISTER_THREAD(ct.tid()); #ifndef WINDOWS pthread_detach((ct.__privateinitializer__.p)->thread); @@ -396,6 +464,7 @@ void PIThread::__thread_func_once__(void * t) { ct.tid_ = GetCurrentThreadId(); #endif PIINTROSPECTION_REGISTER_THREAD(ct.tid(), ct.priority(), ct.name()); + REGISTER_THREAD(&ct); ct.running_ = true; ct.begin(); ct.started(); @@ -409,6 +478,7 @@ void PIThread::__thread_func_once__(void * t) { ct.tid_ = -1; //cout << "thread " << t << " exiting ... " << endl; //piCout << "pthread_exit" << (ct.__privateinitializer__.p)->thread; + UNREGISTER_THREAD(&ct); PIINTROSPECTION_UNREGISTER_THREAD(ct.tid()); #ifndef WINDOWS pthread_detach((ct.__privateinitializer__.p)->thread); diff --git a/src_main/thread/pithread.h b/src_main/thread/pithread.h index 031a97a5..ce122480 100755 --- a/src_main/thread/pithread.h +++ b/src_main/thread/pithread.h @@ -29,6 +29,33 @@ #include "pimutex.h" #include "piobject.h" +class PIThread; + +class __PIThreadCollection { +public: + static __PIThreadCollection * instance(); + void registerThread(PIThread * t); + void unregisterThread(PIThread * t); + PIVector threads() const; + void lock() {mutex.lock();} + void unlock() {mutex.unlock();} +private: + PIVector threads_; + mutable PIMutex mutex; +}; + + +class __PIThreadCollection_Initializer__ { +public: + __PIThreadCollection_Initializer__(); + ~__PIThreadCollection_Initializer__(); + static int count_; + static __PIThreadCollection * __instance__; +}; + +static __PIThreadCollection_Initializer__ __PIThreadCollection_initializer__; + + typedef void (*ThreadFunc)(void * ); class PIP_EXPORT PIThread: public PIObject @@ -98,6 +125,8 @@ public: //! \brief Returns thread ID llong tid() const {return tid_;} + + void * handle() const; static void __thread_func__(void*); static void __thread_func_once__(void*); @@ -189,11 +218,12 @@ protected: int delay_, policy_; llong tid_; void * data_; - PIMutex mutex_; + mutable PIMutex mutex_; PITimeMeasurer tmf_, tms_, tmr_; PIThread::Priority priority_; ThreadFunc ret_func; PRIVATE_DECLARATION }; + #endif // PITHREAD_H diff --git a/utils/system_daemon/daemon.cpp b/utils/system_daemon/daemon.cpp index c1aaf030..c09ed828 100644 --- a/utils/system_daemon/daemon.cpp +++ b/utils/system_daemon/daemon.cpp @@ -5,6 +5,7 @@ const char self_name[] = "__self__"; extern PIScreen * screen; +extern PISystemMonitor sys_mon; //bool Daemon::inited__ = false; Daemon::Remote::Remote(const PIString & n): PIThread() { @@ -467,6 +468,13 @@ void Daemon::tileEvent(PIScreenTile * t, TileEvent e) { void Daemon::keyEvent(PIKbdListener::KeyEvent key) { + /*if (key.key == PIKbdListener::F2) { + PICout::setBufferActive(true, true); + piCout << sys_mon.threadsStatistic(); + PIFile f("_.txt", PIIODevice::ReadWrite); + f.clear(); + f << PICout::buffer(true); + }*/ if (!tile_root->visible) return; if (screen->dialogTile()) return; switch (key.key) { diff --git a/utils/system_daemon/main.cpp b/utils/system_daemon/main.cpp index ac20a145..87dd8088 100755 --- a/utils/system_daemon/main.cpp +++ b/utils/system_daemon/main.cpp @@ -101,15 +101,17 @@ public: return ret; } PIScreenTile * infoTile() { - TileSimple * ret = new TileSimple(); - ret->content << TileSimple::Row("Exec command: " + PISystemInfo::instance()->execCommand, CellFormat()); - ret->content << TileSimple::Row(" Executed on " + PISystemInfo::instance()->execDateTime.toString(), CellFormat()); - ret->content << TileSimple::Row(" Hostname: " + PISystemInfo::instance()->hostname, CellFormat()); - ret->content << TileSimple::Row(" Username: " + PISystemInfo::instance()->user, CellFormat()); - ret->content << TileSimple::Row(" OS name: " + PISystemInfo::instance()->OS_name, CellFormat()); - ret->content << TileSimple::Row(" OS version: " + PISystemInfo::instance()->OS_version, CellFormat()); - ret->content << TileSimple::Row("Architecture: " + PISystemInfo::instance()->architecture, CellFormat()); - ret->content << TileSimple::Row(" CPU count: " + PIString::fromNumber(PISystemInfo::instance()->processorsCount), CellFormat()); + TileList * ret = new TileList(); + local_info_base << TileList::Row("Exec command: " + PISystemInfo::instance()->execCommand, CellFormat()); + local_info_base << TileList::Row(" Executed on " + PISystemInfo::instance()->execDateTime.toString(), CellFormat()); + local_info_base << TileList::Row(" Hostname: " + PISystemInfo::instance()->hostname, CellFormat()); + local_info_base << TileList::Row(" Username: " + PISystemInfo::instance()->user, CellFormat()); + local_info_base << TileList::Row(" OS name: " + PISystemInfo::instance()->OS_name, CellFormat()); + local_info_base << TileList::Row(" OS version: " + PISystemInfo::instance()->OS_version, CellFormat()); + local_info_base << TileList::Row("Architecture: " + PISystemInfo::instance()->architecture, CellFormat()); + local_info_base << TileList::Row(" CPU count: " + PIString::fromNumber(PISystemInfo::instance()->processorsCount), CellFormat()); + local_info_base << TileList::Row("", CellFormat()); + local_info_base << TileList::Row("PIThreads:", CellFormat()); return ret; } PIScreenTile * peerDiagTile() { @@ -208,9 +210,30 @@ public: daemon_.unlock(); screen->unlock(); } - void tick(void* data_, int delimiter) { + void updateSysMon() { + TileList * tile = (TileList*)tinfo; + PIVector ts = sys_mon.threadsStatistic(); + screen->lock(); + tile->content = local_info_base; + int num = 0, maxlen = 0; + piForeachC (PISystemMonitor::ThreadStats & t, ts) + maxlen = piMaxi(maxlen, t.name.length()); + piForeachC (PISystemMonitor::ThreadStats & t, ts) { + PIString line = PIString(num++).expandLeftTo(2, ' ') + ": "; + line += PIString(t.name).expandRightTo(maxlen, ' ') + ": k "; + PIString ns = PIString::fromNumber(t.cpu_load_kernel); ns = ns.left(ns.find('.') + 2); + line += ns.expandLeftTo(5, ' ') + " %, u "; + ns = PIString::fromNumber(t.cpu_load_user); ns = ns.left(ns.find('.') + 2); + line += ns.expandLeftTo(5, ' ') + " %"; + tile->content << TileList::Row(line, CellFormat()); + } + screen->unlock(); + } + void tick(void* data_, int delimiter) { if (tpeerdiag->visible || tpeer->visible) updatePeerInfo(); + if (tinfo->visible) + updateSysMon(); } EVENT_HANDLER(void, menuRequest) { piForeach (PIScreenTile * t, mtiles) @@ -277,6 +300,7 @@ public: TileSimple * peerinfo_tl, * peerinfo_header; TileSimple * peerdiagdata_tl, * peerdiagservice_tl; PIVector mtiles; + PIDeque local_info_base; int cur_peer; }; @@ -372,6 +396,7 @@ int main(int argc, char * argv[]) { screen->waitForFinish(); screen->stop(true); } + sys_mon.stop(); delete menu; delete daemon; delete screen;