00001 #ifndef Impala_Process_MemoryInfo_h
00002 #define Impala_Process_MemoryInfo_h
00003
00004 #include "Basis/ILog.h"
00005 #include "Basis/String.h"
00006 #include "Basis/NativeTypes.h"
00007 #ifdef WIN32
00008 #include <psapi.h>
00009 #else
00010 #include <unistd.h>
00011 #endif
00012 #include <vector>
00013
00014 namespace Impala
00015 {
00016 namespace Process
00017 {
00018
00019 class MemoryInfo
00020 {
00021 public:
00022
00023 MemoryInfo(CString tag, int dumpFreq)
00024 {
00025 mTag = tag;
00026 mDumpFreq = dumpFreq;
00027 mIsActive = false;
00028 mTotalMemIncr = 0;
00029 mMemFrom = 0;
00030 mNrCalls = 0;
00031 mNrCallsIncr = 0;
00032 mNrCallsDecr = 0;
00033 }
00034
00035
00036 static Int64
00037 GetUsage()
00038 {
00039 Int64 usage = -1;
00040 #ifdef WIN32
00041 PROCESS_MEMORY_COUNTERS info;
00042 bool result = GetProcessMemoryInfo(GetCurrentProcess(), &info,
00043 sizeof(info));
00044 if (result)
00045 {
00046 usage = info.WorkingSetSize + info.QuotaPagedPoolUsage +
00047 info.QuotaNonPagedPoolUsage + info.PagefileUsage;
00048 }
00049 else
00050 {
00051 usage = -2;
00052 }
00053 #else
00054 long pageSize = sysconf(_SC_PAGE_SIZE);
00055 char buf[100];
00056 sprintf(buf, "/proc/%u/statm", (unsigned) getpid());
00057 FILE* fp = fopen(buf, "r");
00058 if (fp)
00059 {
00060 unsigned size;
00061 fscanf(fp, "%u", &size);
00062 usage = (Int64) size * (Int64) pageSize;
00063 fclose(fp);
00064 }
00065 else
00066 {
00067 usage = -2;
00068 }
00069 #endif
00070 return usage;
00071 }
00072
00073 static String
00074 GetUsageString()
00075 {
00076 Int64 usage = GetUsage();
00077 if (usage < 0)
00078 return "no memory info available";
00079 return Bytes2String(usage);
00080 }
00081
00082 static String
00083 Bytes2String(Int64 nr)
00084 {
00085 const char* units[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB"};
00086 String sign("");
00087 if (nr < 0)
00088 {
00089 sign = "-";
00090 nr = -nr;
00091 }
00092 std::vector<int> vec;
00093 for (int i=0 ; i<7 ; i++)
00094 {
00095 vec.push_back(nr % 1024);
00096 nr /= 1024;
00097 }
00098 if (nr != 0)
00099 return "Out of range";
00100 int u = 6;
00101 while ((vec[u] == 0) && (u > 0))
00102 u--;
00103 String val = MakeString(vec[u]);
00104 if (u > 0)
00105 val += "." + MakeString(vec[u-1]);
00106 return sign + val + String(units[u]);
00107 }
00108
00109 static void
00110 PrintUsage(CString message)
00111 {
00112 ILOG_INFO("print usage");
00113 Int64 nr = GetUsage();
00114 if (nr < 0)
00115 {
00116 ILOG_INFO("Could not establish memory usage");
00117 }
00118 else
00119 {
00120 ILOG_INFO(message << ", usage = " << nr << " = " << Bytes2String(nr));
00121 }
00122 }
00123
00124 void
00125 MarkFrom()
00126 {
00127 if (mIsActive)
00128 {
00129 ILOG_WARN("Already active (" << mTag << ")");
00130 return;
00131 }
00132 mMemFrom = GetUsage();
00133 mIsActive = true;
00134 }
00135
00136 Int64
00137 GetUsageSinceMark()
00138 {
00139 if (!mIsActive)
00140 {
00141 ILOG_WARN("Not active (" << mTag << ")");
00142 return -1;
00143 }
00144 return GetUsage() - mMemFrom;
00145 }
00146
00147 String
00148 GetUsageSinceMarkString()
00149 {
00150 if (!mIsActive)
00151 {
00152 ILOG_WARN("Not active (" << mTag << ")");
00153 return "not active";
00154 }
00155 Int64 memIncr = GetUsage() - mMemFrom;
00156 return Bytes2String(memIncr);
00157 }
00158
00159 void
00160 MarkTo()
00161 {
00162 if (!mIsActive)
00163 {
00164 ILOG_WARN("Not active (" << mTag << ")");
00165 return;
00166 }
00167 mNrCalls++;
00168 Int64 memTo = GetUsage();
00169 Int64 memIncr = memTo - mMemFrom;
00170 if (memIncr != 0)
00171 {
00172 if (mMemFrom < memTo)
00173 mNrCallsIncr++;
00174 else
00175 mNrCallsDecr++;
00176 mTotalMemIncr += memIncr;
00177 }
00178 mIsActive = false;
00179
00180 if (mDumpFreq > 0)
00181 if (mNrCalls % mDumpFreq == 0)
00182 Dump();
00183 }
00184
00185 void
00186 Dump()
00187 {
00188 if (mIsActive)
00189 ILOG_WARN("Still active (" << mTag << ")");
00190
00191 Int64 avg = mTotalMemIncr / Int64(mNrCalls);
00192 ILOG_INFO("Dump (" << mTag << ") : " <<
00193 "NrCalls=" << mNrCalls <<
00194 ", TotalMemIncr=" << mTotalMemIncr <<
00195 " (" << Bytes2String(mTotalMemIncr) << ")" <<
00196 ", AvgMemIncr=" << avg <<
00197 " (" << Bytes2String(avg) << ")" <<
00198 ", NrCallsIncr=" << mNrCallsIncr <<
00199 ", NrCallsDecr=" << mNrCallsDecr);
00200 }
00201
00202 private:
00203
00204 String mTag;
00205 int mDumpFreq;
00206 bool mIsActive;
00207 Int64 mTotalMemIncr;
00208 Int64 mMemFrom;
00209 int mNrCalls;
00210 int mNrCallsIncr;
00211 int mNrCallsDecr;
00212
00213 ILOG_VAR_DECL;
00214
00215 };
00216
00217 ILOG_VAR_INIT(MemoryInfo, Impala.Process);
00218
00219 }
00220 }
00221
00222 #endif