00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <sys/types.h>
00036 #include <inttypes.h>
00037
00038
00039
00040 #include <boost/lexical_cast.hpp>
00041
00042 #include "LoadMonitor.h"
00043
00044 #include "Log.h"
00045 #include "TimeUtil.h"
00046 #include "massert.h"
00047 #include "params.h"
00048
00049
00050
00051 using namespace std;
00052
00053 LoadMonitor* LoadMonitor::instance = 0;
00054 HiResLoadMonitor* HiResLoadMonitor::instance = 0;
00055
00056 HiResLoadMonitor::HiResLoadMonitor(uint64_t freq) : halt(false), frequency(freq) {
00057 pid = getpid();
00058 path = "/proc/" + boost::lexical_cast<string>(pid) + "/stat";
00059
00060 statfile.open(path.c_str());
00061 if (!statfile.good()) {
00062 Log::perror("open");
00063 assert(0);
00064 }
00065 }
00066
00067 void HiResLoadMonitor::expire() {
00068 assert(instance);
00069 uint64_t now = TimeUtil::timeu();
00070 ProcStat st;
00071 readProcStat(st);
00072 uint64_t t = now - instance->prevTime;
00073
00074 double pu = (st.utime - instance->stat.utime) * 10000.0 / t;
00075 double ps = (st.stime - instance->stat.stime) * 10000.0 / t;
00076 int iu = (int)(100 * pu);
00077 int is = (int)(100 * ps);
00078 int it = iu + is;
00079 Log::logf("HiResLoadMonitor", "%d %d %d %u %d", iu, is, it, st.vsize, st.rss);
00080
00081 instance->stat = st;
00082 instance->prevTime = now;
00083
00084 if (!halt) {
00085 schedule(frequency);
00086 }
00087 }
00088
00089 void HiResLoadMonitor::readProcStat(ProcStat& st) {
00090 statfile.seekg(0, ios::beg);
00091 string tmp;
00092 int i;
00093 uint u;
00094 statfile >> i
00095 >> tmp
00096 >> tmp
00097 >> i
00098 >> i
00099 >> i
00100 >> i
00101 >> i
00102 >> i
00103 >> i
00104 >> i
00105 >> i
00106 >> i
00107 >> st.utime
00108 >> st.stime
00109 >> i
00110 >> i
00111 >> i
00112 >> i
00113 >> i
00114 >> i
00115 >> u
00116 >> st.vsize
00117 >> st.rss
00118 ;
00119 }
00120
00121 void HiResLoadMonitor::start(uint64_t freq) {
00122 if (instance == 0) {
00123 instance = new HiResLoadMonitor(freq);
00124 }
00125 else {
00126 instance->frequency = freq;
00127 }
00128
00129 instance->cancel();
00130 instance->schedule(instance->frequency);
00131 instance->prevTime = TimeUtil::timeu();
00132 instance->readProcStat(instance->stat);
00133 }
00134
00135 void HiResLoadMonitor::stop() {
00136 instance->halt = true;
00137 }
00138
00139 void LoadMonitor::runLoadMonitor() {
00140
00141 if (instance == 0) {
00142 instance = new LoadMonitor();
00143 }
00144 if (instance->loadfile.good() && instance->cpufile.good()) {
00145 instance->cancel();
00146 instance->schedule(instance->frequency);
00147 }
00148 }
00149
00150 void LoadMonitor::stopLoadMonitor() {
00151 instance->halt = true;
00152 }
00153
00154 LoadMonitor::LoadMonitor() : halt(false), frequency(DEFAULT_FREQUENCY),
00155 load(0), lastCPU_sum(0) {
00156
00157 memset(curLoad, 0, sizeof(curLoad));
00158 memset(lastCPU, 0, sizeof(lastCPU));
00159 memset(curCPU, 0, sizeof(curCPU));
00160 memset(peakload, 0, sizeof(peakload));
00161
00162 loadfile.open("/proc/loadavg");
00163 if (!loadfile.good()) {
00164 perror( "REPLAY error opening /proc/loadavg" );
00165 return;
00166 }
00167
00168 cpufile.open("/proc/stat");
00169 if (!cpufile.good()) {
00170 perror( "REPLAY error opening /proc/stat" );
00171 return;
00172 }
00173
00174 if( params::containsKey(params::MACE_LOAD_MONITOR_FREQUENCY_MS))
00175 {
00176 frequency = (int)(params::get<int>(params::MACE_LOAD_MONITOR_FREQUENCY_MS) * 1000);
00177 }
00178
00179 Log::logf("LoadMonitor", "REPLAY CPU monitoring frequency is %" PRIu64
00180 " usecs.", frequency );
00181
00182 string tmp;
00183 cpufile >> tmp >> lastCPU[0] >> lastCPU[1] >> lastCPU[2] >> lastCPU[3];
00184 assert(tmp == "cpu");
00185 cpufile.seekg(0, ios::beg);
00186
00187 lastCPU_sum = lastCPU[0] + lastCPU[1] + lastCPU[2] + lastCPU[3];
00188 }
00189
00190 void LoadMonitor::expire() {
00191 static string tmp;
00192
00193
00194
00195 loadfile >> curLoad[0] >> curLoad[1] >> curLoad[2];
00196 loadfile.seekg(0, ios::beg);
00197
00198 Log::logf("LoadMonitor", "REPLAY CPU load: %.2f %.2f %.2f",
00199 curLoad[0], curLoad[1], curLoad[2]);
00200
00201 for(int i = 0; i < 3; ++i) {
00202 if (curLoad[i] > peakload[i]) {
00203 peakload[i] = curLoad[i];
00204 }
00205 }
00206
00207 Log::logf("LoadMonitor", "Peak CPU load : %.2f %.2f %.2f",
00208 peakload[0], peakload[1], peakload[2]);
00209
00210 cpufile >> tmp >> curCPU[0] >> curCPU[1] >> curCPU[2] >> curCPU[3];
00211 assert(tmp == "cpu");
00212 cpufile.seekg(0, ios::beg);
00213
00214 uint32_t curCPU_sum = curCPU[0] + curCPU[1] + curCPU[2] + curCPU[3];
00215
00216 float time_diff = (float) curCPU_sum - (float) lastCPU_sum;
00217 float user = ((float) curCPU[0] - lastCPU[0]) / time_diff * 100;
00218 float nice = ((float) curCPU[1] - lastCPU[1]) / time_diff * 100;
00219 float system = ((float) curCPU[2] - lastCPU[2]) / time_diff * 100;
00220 float idle = ((float) curCPU[3] - lastCPU[3]) / time_diff * 100;
00221
00222
00223
00224
00225 Log::logf("LoadMonitor", "REPLAY CPU time: u %.2f %% n %.2f %% s %.2f %% i %.2f %%",
00226 user, nice, system, idle);
00227
00228 lastCPU_sum = 0;
00229 for (size_t i = 0; i < 4; i++) {
00230 lastCPU[i] = curCPU[i];
00231 lastCPU_sum += lastCPU[i];
00232 }
00233
00234 if (!halt) {
00235 schedule(frequency);
00236 }
00237 }
00238