diff --git a/base/SConscript b/base/SConscript index 1203a204..33a90498 100644 --- a/base/SConscript +++ b/base/SConscript @@ -34,7 +34,10 @@ for src in CpuInfoSandeshGenSrcs: obj = env.Object(objname, src) cpuinfo_sandesh_files_.append(obj) -libcpuinfo = env.Library('cpuinfo', ['cpuinfo.cc'] + cpuinfo_sandesh_files_) +if sys.platform == 'win32': + libcpuinfo = env.Library('cpuinfo', ['cpuinfo_common.cc', 'windows/cpuinfo.cc'] + cpuinfo_sandesh_files_) +else: + libcpuinfo = env.Library('cpuinfo', ['cpuinfo_common.cc', 'linux/cpuinfo.cc'] + cpuinfo_sandesh_files_) task = except_env.Object('task.o', 'task.cc') timer = timer_env.Object('timer.o', 'timer.cc') diff --git a/base/cpuinfo.cc b/base/cpuinfo.cc deleted file mode 100644 index 0f71a9b1..00000000 --- a/base/cpuinfo.cc +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. - */ - -#if defined(__APPLE__) -#include -#include -#include -#include -#elif defined(_WIN32) -#include -#include -#endif - -#include "sys/times.h" -#include -#include - -#include -#include - -#include -#include -#include - -using namespace boost; - -static uint32_t NumCpus() { - static uint32_t count = 0; - - if (count != 0) { - return count; - } - -#if defined(__APPLE__) - size_t len = sizeof(count); - sysctlbyname("hw.logicalcpu", &count, &len, NULL, 0); - return count; -#elif defined(_WIN32) - return count = std::thread::hardware_concurrency(); -#else - std::ifstream file("/proc/cpuinfo"); - std::string content((std::istreambuf_iterator(file)), - std::istreambuf_iterator()); - // Create a find_iterator - typedef find_iterator string_find_iterator; - - for(string_find_iterator it = - make_find_iterator(content, first_finder("model name", is_iequal())); - it!=string_find_iterator(); ++it, count++); - return count; -#endif -} - -static void LoadAvg(CpuLoad &load) { - double averages[3]; - uint32_t num_cpus = NumCpus(); - getloadavg(averages, 3); - if (num_cpus > 0) { - load.one_min_avg = averages[0]/num_cpus; - load.five_min_avg = averages[1]/num_cpus; - load.fifteen_min_avg = averages[2]/num_cpus; - } -} - -static void ProcessMemInfo(ProcessMemInfo &info) { -#if defined(__APPLE__) - struct task_basic_info t_info; - mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; - if (KERN_SUCCESS != task_info(mach_task_self(), - TASK_BASIC_INFO, - (task_info_t)&t_info, - &t_info_count)) { - return; - } - info.res = t_info.resident_size; - info.virt = t_info.virtual_size; - // XXX Peak virt not availabe, just fill in virt - info.peakvirt = t_info.virtual_size; - return; -#elif defined(_WIN32) - // TODO(WINDOWS) JW-1121 -#else - std::ifstream file("/proc/self/status"); - bool vmsize = false; - bool peak = false; - bool rss = false; - std::string line; - while (std::getline(file, line)) { - if (line.find("VmSize") != std::string::npos) { - std::stringstream vm(line); - std::string tmp; vm >> tmp; vm >> info.virt; - vmsize = true; - } - if (line.find("VmRSS") != std::string::npos) { - std::stringstream vm(line); - std::string tmp; vm >> tmp; vm >> info.res; - rss = true; - } - if (line.find("VmPeak") != std::string::npos) { - std::stringstream vm(line); - std::string tmp; vm >> tmp; vm >> info.peakvirt; - peak = true; - } - if (rss && vmsize && peak) - break; - } -#endif -} - -static void SystemMemInfo(SystemMemInfo &info) { -#if defined(_WIN32) - // TODO(WINDOWS) JW-1121 -#else - std::ifstream file("/proc/meminfo"); - std::string tmp; - // MemTotal: 132010576 kB - file >> tmp; file >> info.total; file >> tmp; - // MemFree: 90333184 kB - file >> tmp; file >> info.free; file >> tmp; - // Buffers: 1029924 kB - file >> tmp; file >> info.buffers; file >> tmp; - // Cached: 10290012 kB - file >> tmp; file >> info.cached; - // Used = Total - Free - info.used = info.total - info.free; -#endif -} - -static clock_t snapshot, prev_sys_cpu, prev_user_cpu; - -static void ProcessCpuShare(double &percentage) { - struct tms cpu_taken; - clock_t now; - - now = times(&cpu_taken); - if (now <= snapshot || cpu_taken.tms_stime < prev_sys_cpu || - cpu_taken.tms_utime < prev_user_cpu) { - percentage = -1.0; - } else { - percentage = - (double)((cpu_taken.tms_stime - prev_sys_cpu) + - (cpu_taken.tms_utime - prev_user_cpu)) / (now - snapshot); - percentage *= 100; - percentage /= NumCpus(); - } - snapshot = now; - prev_sys_cpu = cpu_taken.tms_stime; - prev_user_cpu = cpu_taken.tms_utime; -} - -void CpuLoadData::GetCpuLoadInfo(CpuInfo &info, bool system) { - if (system) { - LoadAvg(info.load_avg); - SystemMemInfo(info.sys_mem_info); - } - - ProcessMemInfo(info.mem_info); - - ProcessCpuShare(info.process_cpu_share); - info.num_cpu = NumCpus(); -} - -void CpuLoadData::Init() { - struct tms cpu_taken; - snapshot = times(&cpu_taken); - prev_sys_cpu = cpu_taken.tms_stime; - prev_user_cpu = cpu_taken.tms_utime; -} - -void CpuLoadData::FillCpuInfo(CpuLoadInfo &cpu_load_info, bool system) { - CpuInfo info; - CpuLoadData::GetCpuLoadInfo(info, system); - cpu_load_info.set_num_cpu(info.num_cpu); - MemInfo mem_info; - mem_info.set_virt(info.mem_info.virt); - mem_info.set_peakvirt(info.mem_info.peakvirt); - mem_info.set_res(info.mem_info.res); - cpu_load_info.set_meminfo(mem_info); - - cpu_load_info.set_cpu_share(info.process_cpu_share); - - if (system) { - CpuLoadAvg load_avg; - load_avg.set_one_min_avg(info.load_avg.one_min_avg); - load_avg.set_five_min_avg(info.load_avg.five_min_avg); - load_avg.set_fifteen_min_avg(info.load_avg.fifteen_min_avg); - cpu_load_info.set_cpuload(load_avg); - - SysMemInfo sys_mem_info; - sys_mem_info.set_total(info.sys_mem_info.total); - sys_mem_info.set_used(info.sys_mem_info.used); - sys_mem_info.set_free(info.sys_mem_info.free); - sys_mem_info.set_buffers(info.sys_mem_info.buffers); - sys_mem_info.set_cached(info.sys_mem_info.cached); - cpu_load_info.set_sys_mem_info(sys_mem_info); - } -} - -void CpuLoadInfoReq::HandleRequest() const { - CpuLoadInfo cpu_load_info; - CpuLoadData::FillCpuInfo(cpu_load_info, true); - - CpuLoadInfoResp *resp = new CpuLoadInfoResp; - resp->set_cpu_info(cpu_load_info); - resp->set_context(context()); - resp->Response(); -} - -void PopulateProcessCpuInfo(const CpuLoadInfo &cpu_load_info, - ProcessCpuInfo *pinfo) { - pinfo->set_module_id(Sandesh::module()); - pinfo->set_inst_id(Sandesh::instance_id()); - pinfo->set_cpu_share(cpu_load_info.get_cpu_share()); - pinfo->set_mem_virt(cpu_load_info.get_meminfo().get_virt()); - pinfo->set_mem_res(cpu_load_info.get_meminfo().get_res()); -} diff --git a/base/cpuinfo_common.cc b/base/cpuinfo_common.cc new file mode 100755 index 00000000..99218cd3 --- /dev/null +++ b/base/cpuinfo_common.cc @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include "sys/times.h" +#include +#include + +#include +#include + +extern void LoadAvg(CpuLoad &load); +extern uint32_t NumCpus(); + +static clock_t snapshot, prev_sys_cpu, prev_user_cpu; + +static void ProcessCpuShare(double &percentage) { + struct tms cpu_taken; + clock_t now; + + now = times(&cpu_taken); + if (now <= snapshot || cpu_taken.tms_stime < prev_sys_cpu || + cpu_taken.tms_utime < prev_user_cpu) { + percentage = -1.0; + } else { + percentage = + (double)((cpu_taken.tms_stime - prev_sys_cpu) + + (cpu_taken.tms_utime - prev_user_cpu)) / (now - snapshot); + percentage *= 100; + percentage /= NumCpus(); + } + snapshot = now; + prev_sys_cpu = cpu_taken.tms_stime; + prev_user_cpu = cpu_taken.tms_utime; +} + +void CpuLoadData::GetCpuLoadInfo(CpuInfo &info, bool system) { + if (system) { + LoadAvg(info.load_avg); + SystemMemInfo(info.sys_mem_info); + } + + ProcessMemInfo(info.mem_info); + + ProcessCpuShare(info.process_cpu_share); + info.num_cpu = NumCpus(); +} + +void CpuLoadData::Init() { + struct tms cpu_taken; + snapshot = times(&cpu_taken); + prev_sys_cpu = cpu_taken.tms_stime; + prev_user_cpu = cpu_taken.tms_utime; +} + +void CpuLoadData::FillCpuInfo(CpuLoadInfo &cpu_load_info, bool system) { + CpuInfo info; + CpuLoadData::GetCpuLoadInfo(info, system); + cpu_load_info.set_num_cpu(info.num_cpu); + MemInfo mem_info; + mem_info.set_virt(info.mem_info.virt); + mem_info.set_peakvirt(info.mem_info.peakvirt); + mem_info.set_res(info.mem_info.res); + cpu_load_info.set_meminfo(mem_info); + + cpu_load_info.set_cpu_share(info.process_cpu_share); + + if (system) { + CpuLoadAvg load_avg; + load_avg.set_one_min_avg(info.load_avg.one_min_avg); + load_avg.set_five_min_avg(info.load_avg.five_min_avg); + load_avg.set_fifteen_min_avg(info.load_avg.fifteen_min_avg); + cpu_load_info.set_cpuload(load_avg); + + SysMemInfo sys_mem_info; + sys_mem_info.set_total(info.sys_mem_info.total); + sys_mem_info.set_used(info.sys_mem_info.used); + sys_mem_info.set_free(info.sys_mem_info.free); + sys_mem_info.set_buffers(info.sys_mem_info.buffers); + sys_mem_info.set_cached(info.sys_mem_info.cached); + cpu_load_info.set_sys_mem_info(sys_mem_info); + } +} + +void CpuLoadInfoReq::HandleRequest() const { + CpuLoadInfo cpu_load_info; + CpuLoadData::FillCpuInfo(cpu_load_info, true); + + CpuLoadInfoResp *resp = new CpuLoadInfoResp; + resp->set_cpu_info(cpu_load_info); + resp->set_context(context()); + resp->Response(); +} + +void PopulateProcessCpuInfo(const CpuLoadInfo &cpu_load_info, + ProcessCpuInfo *pinfo) { + pinfo->set_module_id(Sandesh::module()); + pinfo->set_inst_id(Sandesh::instance_id()); + pinfo->set_cpu_share(cpu_load_info.get_cpu_share()); + pinfo->set_mem_virt(cpu_load_info.get_meminfo().get_virt()); + pinfo->set_mem_res(cpu_load_info.get_meminfo().get_res()); +} \ No newline at end of file diff --git a/base/linux/cpuinfo.cc b/base/linux/cpuinfo.cc new file mode 100644 index 00000000..9b5ebdb8 --- /dev/null +++ b/base/linux/cpuinfo.cc @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include "sys/times.h" +#include +#include + +#include +#include + +#include +#include +#include + +using namespace boost; + +uint32_t NumCpus() { + static uint32_t count = 0; + + if (count != 0) { + return count; + } + + std::ifstream file("/proc/cpuinfo"); + std::string content((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); + // Create a find_iterator + typedef find_iterator string_find_iterator; + + for (string_find_iterator it = + make_find_iterator(content, first_finder("model name", is_iequal())); + it != string_find_iterator(); ++it, count++); + return count; +} + +void LoadAvg(CpuLoad &load) { + double averages[3]; + uint32_t num_cpus = NumCpus(); + getloadavg(averages, 3); + if (num_cpus > 0) { + load.one_min_avg = averages[0]/num_cpus; + load.five_min_avg = averages[1]/num_cpus; + load.fifteen_min_avg = averages[2]/num_cpus; + } +} + + + +void ProcessMemInfo(ProcessMemInfo &info) { + std::ifstream file("/proc/self/status"); + bool vmsize = false; + bool peak = false; + bool rss = false; + std::string line; + while (std::getline(file, line)) { + if (line.find("VmSize") != std::string::npos) { + std::stringstream vm(line); + std::string tmp; vm >> tmp; vm >> info.virt; + vmsize = true; + } + if (line.find("VmRSS") != std::string::npos) { + std::stringstream vm(line); + std::string tmp; vm >> tmp; vm >> info.res; + rss = true; + } + if (line.find("VmPeak") != std::string::npos) { + std::stringstream vm(line); + std::string tmp; vm >> tmp; vm >> info.peakvirt; + peak = true; + } + if (rss && vmsize && peak) + break; + } +} + +void SystemMemInfo(SystemMemInfo &info) { + std::ifstream file("/proc/meminfo"); + std::string tmp; + // MemTotal: 132010576 kB + file >> tmp; file >> info.total; file >> tmp; + // MemFree: 90333184 kB + file >> tmp; file >> info.free; file >> tmp; + // Buffers: 1029924 kB + file >> tmp; file >> info.buffers; file >> tmp; + // Cached: 10290012 kB + file >> tmp; file >> info.cached; + // Used = Total - Free + info.used = info.total - info.free; +} \ No newline at end of file diff --git a/base/windows/cpuinfo.cc b/base/windows/cpuinfo.cc new file mode 100644 index 00000000..e6f527c6 --- /dev/null +++ b/base/windows/cpuinfo.cc @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include //needed for process information +#include //needed for process information +#include +#include + +#include "sys/times.h" +#include +#include + +#include +#include + +uint32_t NumCpus() { + static uint32_t count = 0; + + if (count != 0) { + return count; + } + + return count = std::thread::hardware_concurrency(); +} + +void ProcessMemInfo(ProcessMemInfo &info) { + PROCESS_MEMORY_COUNTERS mctr; + if (GetProcessMemoryInfo(GetCurrentProcess(), &mctr, sizeof(mctr))) { + info.res = mctr.WorkingSetSize/1024; + info.virt = mctr.PagefileUsage/1024;//returned values are in bytes and workingsetSize is closes to both res and virt. + info.peakvirt = mctr.PeakPagefileUsage/1024; + } +} + +void SystemMemInfo(SystemMemInfo &info) { + memset(&info, 0, sizeof(info));//set to zero to prevent random values + PERFORMANCE_INFORMATION pi; + if (GetPerformanceInfo(&pi, sizeof(pi))) { + info.total = (pi.PhysicalTotal*pi.PageSize)/1024; + info.free = (pi.PhysicalAvailable*pi.PageSize) / 1024; + info.buffers = 0; + info.cached = (pi.SystemCache*pi.PageSize)/1024; + info.used = info.total - info.free; + } +} + +void LoadAvg(CpuLoad &load) { + double average=0; + uint32_t num_cpus = NumCpus(); + getloadavg(&average, 1); + if (num_cpus > 0) { + load.one_min_avg = load.five_min_avg = load.fifteen_min_avg = average/num_cpus; + } +}