From 15aea4d9b37d88c50d9ec50ff47bb65e35cbcb5d Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 19 Apr 2014 23:18:00 +0800 Subject: [PATCH] add cpuinfo --- trunk/src/app/srs_app_http_api.cpp | 17 +- trunk/src/app/srs_app_server.cpp | 4 +- trunk/src/kernel/srs_kernel_utility.cpp | 231 +++++++++++++++++++----- trunk/src/kernel/srs_kernel_utility.hpp | 29 +++ 4 files changed, 230 insertions(+), 51 deletions(-) diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 1732098c7..d9bf9f4a4 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -201,6 +201,7 @@ int SrsApiSummaries::do_process_request(SrsSocket* skt, SrsHttpMessage* req) SrsRusage* r = srs_get_system_rusage(); SrsProcSelfStat* u = srs_get_self_proc_stat(); SrsProcSystemStat* s = srs_get_system_proc_stat(); + SrsCpuInfo* c = srs_get_cpuinfo(); ss << JOBJECT_START << JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT @@ -211,7 +212,12 @@ int SrsApiSummaries::do_process_request(SrsSocket* skt, SrsHttpMessage* req) << JFIELD_ORG("rusage_ok", (r->ok? "true":"false")) << JFIELD_CONT << JFIELD_ORG("self_cpu_stat_ok", (u->ok? "true":"false")) << JFIELD_CONT << JFIELD_ORG("system_cpu_stat_ok", (s->ok? "true":"false")) << JFIELD_CONT + << JFIELD_ORG("cpuinfo_ok", (c->ok? "true":"false")) << JFIELD_CONT << JFIELD_ORG("mem_kbyte", r->r.ru_maxrss) << JFIELD_CONT + << JFIELD_ORG("system_cpu", s->percent) << JFIELD_CONT + << JFIELD_ORG("self_cpu", u->percent) << JFIELD_CONT + << JFIELD_ORG("nb_processors", c->nb_processors) << JFIELD_CONT + << JFIELD_ORG("nb_processors_online", c->nb_processors_online) << JFIELD_CONT << JFIELD_ORG("ppid", u->ppid) << JOBJECT_END << JOBJECT_END; @@ -241,7 +247,8 @@ int SrsApiRusages::do_process_request(SrsSocket* skt, SrsHttpMessage* req) ss << JOBJECT_START << JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT << JFIELD_ORG("data", JOBJECT_START) - << JFIELD_ORG("rusage_ok", (r->ok? "true":"false")) << JFIELD_CONT + << JFIELD_ORG("ok", (r->ok? "true":"false")) << JFIELD_CONT + << JFIELD_ORG("sample_time", r->sample_time) << JFIELD_CONT << JFIELD_ORG("ru_utime", r->r.ru_utime.tv_sec) << JFIELD_CONT << JFIELD_ORG("ru_stime", r->r.ru_stime.tv_sec) << JFIELD_CONT << JFIELD_ORG("ru_maxrss", r->r.ru_maxrss) << JFIELD_CONT @@ -286,7 +293,9 @@ int SrsApiSelfProcStats::do_process_request(SrsSocket* skt, SrsHttpMessage* req) ss << JOBJECT_START << JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT << JFIELD_ORG("data", JOBJECT_START) - << JFIELD_ORG("self_cpu_stat_ok", (u->ok? "true":"false")) << JFIELD_CONT + << JFIELD_ORG("ok", (u->ok? "true":"false")) << JFIELD_CONT + << JFIELD_ORG("sample_time", u->sample_time) << JFIELD_CONT + << JFIELD_ORG("percent", u->percent) << JFIELD_CONT << JFIELD_ORG("pid", u->pid) << JFIELD_CONT << JFIELD_STR("comm", u->comm) << JFIELD_CONT << JFIELD_STR("state", u->state) << JFIELD_CONT @@ -359,7 +368,9 @@ int SrsApiSystemProcStats::do_process_request(SrsSocket* skt, SrsHttpMessage* re ss << JOBJECT_START << JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT << JFIELD_ORG("data", JOBJECT_START) - << JFIELD_ORG("system_cpu_stat_ok", (s->ok? "true":"false")) << JFIELD_CONT + << JFIELD_ORG("ok", (s->ok? "true":"false")) << JFIELD_CONT + << JFIELD_ORG("sample_time", s->sample_time) << JFIELD_CONT + << JFIELD_ORG("percent", s->percent) << JFIELD_CONT << JFIELD_ORG("user", s->user) << JFIELD_CONT << JFIELD_ORG("nice", s->nice) << JFIELD_CONT << JFIELD_ORG("sys", s->sys) << JFIELD_CONT diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index a55a76756..11af202bd 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -56,11 +56,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // update rusage interval: // SRS_SYS_CYCLE_INTERVAL * SRS_SYS_RUSAGE_RESOLUTION_TIMES -#define SRS_SYS_RUSAGE_RESOLUTION_TIMES 15 +#define SRS_SYS_RUSAGE_RESOLUTION_TIMES 30 // update rusage interval: // SRS_SYS_CYCLE_INTERVAL * SRS_SYS_CPU_STAT_RESOLUTION_TIMES -#define SRS_SYS_CPU_STAT_RESOLUTION_TIMES 15 +#define SRS_SYS_CPU_STAT_RESOLUTION_TIMES 30 SrsListener::SrsListener(SrsServer* server, SrsListenerType type) { diff --git a/trunk/src/kernel/srs_kernel_utility.cpp b/trunk/src/kernel/srs_kernel_utility.cpp index 67a51eeaa..1bc06ee90 100644 --- a/trunk/src/kernel/srs_kernel_utility.cpp +++ b/trunk/src/kernel/srs_kernel_utility.cpp @@ -63,6 +63,7 @@ static SrsRusage _srs_system_rusage; SrsRusage::SrsRusage() { ok = false; + sample_time = 0; memset(&r, 0, sizeof(rusage)); } @@ -77,6 +78,9 @@ void srs_update_system_rusage() srs_warn("getrusage failed, ignore"); return; } + + srs_update_system_time_ms(); + _srs_system_rusage.sample_time = srs_get_system_time_ms(); _srs_system_rusage.ok = true; } @@ -87,11 +91,70 @@ static SrsProcSystemStat _srs_system_cpu_system_stat; SrsProcSelfStat::SrsProcSelfStat() { ok = false; + sample_time = 0; + percent = 0; + + pid = 0; + memset(comm, 0, sizeof(comm)); + state = 0; + ppid = 0; + pgrp = 0; + session = 0; + tty_nr = 0; + tpgid = 0; + flags = 0; + minflt = 0; + cminflt = 0; + majflt = 0; + cmajflt = 0; + utime = 0; + stime = 0; + cutime = 0; + cstime = 0; + priority = 0; + nice = 0; + num_threads = 0; + itrealvalue = 0; + starttime = 0; + vsize = 0; + rss = 0; + rsslim = 0; + startcode = 0; + endcode = 0; + startstack = 0; + kstkesp = 0; + kstkeip = 0; + signal = 0; + blocked = 0; + sigignore = 0; + sigcatch = 0; + wchan = 0; + nswap = 0; + cnswap = 0; + exit_signal = 0; + processor = 0; + rt_priority = 0; + policy = 0; + delayacct_blkio_ticks = 0; + guest_time = 0; + cguest_time = 0; } SrsProcSystemStat::SrsProcSystemStat() { ok = false; + sample_time = 0; + percent = 0; + memset(label, 0, sizeof(label)); + user = 0; + nice = 0; + sys = 0; + idle = 0; + iowait = 0; + irq = 0; + softirq = 0; + steal = 0; + guest = 0; } SrsProcSelfStat* srs_get_self_proc_stat() @@ -104,69 +167,145 @@ SrsProcSystemStat* srs_get_system_proc_stat() return &_srs_system_cpu_system_stat; } +bool get_proc_system_stat(SrsProcSystemStat& r) +{ + FILE* f = fopen("/proc/stat", "r"); + if (f == NULL) { + srs_warn("open system cpu stat failed, ignore"); + return false; + } + + for (;;) { + int ret = fscanf(f, "%4s %lu %lu %lu %lu %lu " + "%lu %lu %lu %lu\n", + r.label, &r.user, &r.nice, &r.sys, &r.idle, &r.iowait, + &r.irq, &r.softirq, &r.steal, &r.guest); + r.ok = false; + + if (ret == EOF) { + break; + } + + if (strcmp("cpu", r.label) == 0) { + r.ok = true; + break; + } + } + + fclose(f); + + return r.ok; +} + +bool get_proc_self_stat(SrsProcSelfStat& r) +{ + FILE* f = fopen("/proc/self/stat", "r"); + if (f == NULL) { + srs_warn("open self cpu stat failed, ignore"); + return false; + } + + int ret = fscanf(f, "%d %32s %c %d %d %d %d " + "%d %u %lu %lu %lu %lu " + "%lu %lu %ld %ld %ld %ld " + "%ld %ld %llu %lu %ld " + "%lu %lu %lu %lu %lu " + "%lu %lu %lu %lu %lu " + "%lu %lu %lu %d %d " + "%u %u %llu " + "%lu %ld", + &r.pid, r.comm, &r.state, &r.ppid, &r.pgrp, &r.session, &r.tty_nr, + &r.tpgid, &r.flags, &r.minflt, &r.cminflt, &r.majflt, &r.cmajflt, + &r.utime, &r.stime, &r.cutime, &r.cstime, &r.priority, &r.nice, + &r.num_threads, &r.itrealvalue, &r.starttime, &r.vsize, &r.rss, + &r.rsslim, &r.startcode, &r.endcode, &r.startstack, &r.kstkesp, + &r.kstkeip, &r.signal, &r.blocked, &r.sigignore, &r.sigcatch, + &r.wchan, &r.nswap, &r.cnswap, &r.exit_signal, &r.processor, + &r.rt_priority, &r.policy, &r.delayacct_blkio_ticks, + &r.guest_time, &r.cguest_time); + + if (ret >= 0) { + r.ok = true; + } + + fclose(f); + + return r.ok; +} + void srs_update_proc_stat() { + srs_update_system_time_ms(); + // system cpu stat if (true) { - FILE* f = fopen("/proc/stat", "r"); - if (f == NULL) { - srs_warn("open system cpu stat failed, ignore"); + SrsProcSystemStat r; + if (!get_proc_system_stat(r)) { return; } - SrsProcSystemStat& r = _srs_system_cpu_system_stat; - for (;;) { - int ret = fscanf(f, "%4s %lu %lu %lu %lu %lu " - "%lu %lu %lu %lu\n", - r.label, &r.user, &r.nice, &r.sys, &r.idle, &r.iowait, - &r.irq, &r.softirq, &r.steal, &r.guest); - r.ok = false; - - if (ret == EOF) { - break; - } - - if (strcmp("cpu", r.label) == 0) { - r.ok = true; - break; - } + r.sample_time = srs_get_system_time_ms(); + + // calc usage in percent + SrsProcSystemStat& o = _srs_system_cpu_system_stat; + + // @see: http://blog.csdn.net/nineday/article/details/1928847 + int64_t total = (r.user + r.nice + r.sys + r.idle + r.iowait + r.irq + r.softirq + r.steal + r.guest) + - (o.user + o.nice + o.sys + o.idle + o.iowait + o.irq + o.softirq + o.steal + o.guest); + int64_t idle = r.idle - o.idle; + if (total > 0) { + r.percent = (float)(1 - idle / (double)total); } - fclose(f); + // upate cache. + _srs_system_cpu_system_stat = r; } // self cpu stat if (true) { - FILE* f = fopen("/proc/self/stat", "r"); - if (f == NULL) { - srs_warn("open self cpu stat failed, ignore"); + SrsProcSelfStat r; + if (!get_proc_self_stat(r)) { return; } - SrsProcSelfStat& r = _srs_system_cpu_self_stat; - int ret = fscanf(f, "%d %32s %c %d %d %d %d " - "%d %u %lu %lu %lu %lu " - "%lu %lu %ld %ld %ld %ld " - "%ld %ld %llu %lu %ld " - "%lu %lu %lu %lu %lu " - "%lu %lu %lu %lu %lu " - "%lu %lu %lu %d %d " - "%u %u %llu " - "%lu %ld", - &r.pid, r.comm, &r.state, &r.ppid, &r.pgrp, &r.session, &r.tty_nr, - &r.tpgid, &r.flags, &r.minflt, &r.cminflt, &r.majflt, &r.cmajflt, - &r.utime, &r.stime, &r.cutime, &r.cstime, &r.priority, &r.nice, - &r.num_threads, &r.itrealvalue, &r.starttime, &r.vsize, &r.rss, - &r.rsslim, &r.startcode, &r.endcode, &r.startstack, &r.kstkesp, - &r.kstkeip, &r.signal, &r.blocked, &r.sigignore, &r.sigcatch, - &r.wchan, &r.nswap, &r.cnswap, &r.exit_signal, &r.processor, - &r.rt_priority, &r.policy, &r.delayacct_blkio_ticks, - &r.guest_time, &r.cguest_time); - - if (ret >= 0) { - r.ok = true; + srs_update_system_time_ms(); + r.sample_time = srs_get_system_time_ms(); + + // calc usage in percent + SrsProcSelfStat& o = _srs_system_cpu_self_stat; + + // @see: http://stackoverflow.com/questions/16011677/calculating-cpu-usage-using-proc-files + int64_t total = r.sample_time - o.sample_time; + int64_t usage = (r.utime + r.stime) - (o.utime + o.stime); + if (total > 0) { + r.percent = (float)(usage * 1000 / (double)total / 100); } - fclose(f); + // upate cache. + _srs_system_cpu_self_stat = r; } } + +SrsCpuInfo::SrsCpuInfo() +{ + ok = false; + + nb_processors = 0; + nb_processors_online = 0; +} + +SrsCpuInfo* srs_get_cpuinfo() +{ + static SrsCpuInfo* cpu = NULL; + if (cpu != NULL) { + return cpu; + } + + // initialize cpu info. + cpu = new SrsCpuInfo(); + cpu->ok = true; + cpu->nb_processors = sysconf(_SC_NPROCESSORS_CONF); + cpu->nb_processors_online = sysconf(_SC_NPROCESSORS_ONLN); + + return cpu; +} diff --git a/trunk/src/kernel/srs_kernel_utility.hpp b/trunk/src/kernel/srs_kernel_utility.hpp index 8a02395f0..04b2885a2 100644 --- a/trunk/src/kernel/srs_kernel_utility.hpp +++ b/trunk/src/kernel/srs_kernel_utility.hpp @@ -40,7 +40,11 @@ extern void srs_update_system_time_ms(); // @see: man getrusage struct SrsRusage { + // whether the data is ok. bool ok; + // the time in ms when sample. + int64_t sample_time; + rusage r; SrsRusage(); @@ -56,6 +60,10 @@ struct SrsProcSelfStat { // whether the data is ok. bool ok; + // the time in ms when sample. + int64_t sample_time; + // the percent of usage. 0.153 is 15.3%. + float percent; // pid %d The process ID. int pid; @@ -203,6 +211,10 @@ struct SrsProcSystemStat { // whether the data is ok. bool ok; + // the time in ms when sample. + int64_t sample_time; + // the percent of usage. 0.153 is 15.3%. + float percent; // always be cpu char label[32]; @@ -248,4 +260,21 @@ extern SrsProcSystemStat* srs_get_system_proc_stat(); // the deamon st-thread will update it. extern void srs_update_proc_stat(); +// @see: cat /proc/cpuinfo +struct SrsCpuInfo +{ + // whether the data is ok. + bool ok; + + // The number of processors configured. + int nb_processors; + // The number of processors currently online (available). + int nb_processors_online; + + SrsCpuInfo(); +}; + +// get system cpu info, use cache to avoid performance problem. +extern SrsCpuInfo* srs_get_cpuinfo(); + #endif