00001 #ifndef Impala_Core_Array_ArraySystem_h
00002 #define Impala_Core_Array_ArraySystem_h
00003
00004 #include <cstddef>
00005 #include <map>
00006 #include <iostream>
00007 #include "Basis/ILog.h"
00008 #include "Process/MemoryInfo.h"
00009
00010 namespace Impala
00011 {
00012 namespace Core
00013 {
00014 namespace Array
00015 {
00016
00017
00018 class ArraySystem
00019 {
00020 public:
00021
00022 ~ArraySystem()
00023 {
00024 }
00025
00026 static ArraySystem&
00027 Instance()
00028 {
00029 static ArraySystem theSystem;
00030 return theSystem;
00031 }
00032
00033 template<class StorT>
00034 StorT*
00035 Allocate(size_t n, StorT)
00036 {
00037 size_t oldMem = mMemUse;
00038 mMemUse += n * sizeof(StorT);
00039 mNrAlloc++;
00040 StorT* p = 0;
00041 try
00042 {
00043 p = (StorT*)(operator new(n * sizeof(StorT)));
00044 }
00045 catch (std::bad_alloc)
00046 {
00047 p = 0;
00048 }
00049 if (p == 0)
00050 {
00051 String b = Process::MemoryInfo::Bytes2String(n * sizeof(StorT));
00052 ILOG_ERROR("Couldn't allocate " << n << " x " << sizeof(StorT) <<
00053 " (" << b << ")");
00054 Process::MemoryInfo::PrintUsage("At out of memory");
00055 }
00056 void* vp = p;
00057 ILOG_DEBUG("Alloc (0x" << vp << ") " << n << " times " << sizeof(StorT)
00058 << ", usage from " << oldMem << " to " << mMemUse);
00059 mMap[p] = SysInf(n, sizeof(StorT), mNrAlloc-1);
00060 return p;
00061 }
00062
00063 template<class StorT>
00064 void
00065 Deallocate(StorT* p, size_t n)
00066 {
00067 size_t oldMem = mMemUse;
00068 mMemUse -= n * sizeof(StorT);
00069 mNrDealloc++;
00070 void* vp = p;
00071 operator delete(vp);
00072 ILOG_DEBUG("Dealloc (0x" << vp << ") " << n << " times " << sizeof(StorT)
00073 << ", usage from " << oldMem << " to " << mMemUse);
00074 mMap.erase(p);
00075 }
00076
00077 template<class StorT>
00078 void
00079 External(size_t n, StorT* p)
00080 {
00081 size_t oldMem = mMemUse;
00082 mMemUse += n * sizeof(StorT);
00083 mNrAlloc++;
00084 ILOG_DEBUG("External (0x" << p << ") " << n << " times " << sizeof(StorT)
00085 << ", usage from " << oldMem << " to " << mMemUse);
00086 mMap[p] = SysInf(n, sizeof(StorT), mNrAlloc-1);
00087 }
00088
00089 size_t
00090 MemoryUsage() const
00091 {
00092 return mMemUse;
00093 }
00094
00095 int
00096 NrAlloc() const
00097 {
00098 return mNrAlloc;
00099 }
00100
00101 int
00102 NrDealloc() const
00103 {
00104 return mNrDealloc;
00105 }
00106
00107 int
00108 AllocUsage() const
00109 {
00110 return mNrAlloc - mNrDealloc;
00111 }
00112
00113 void
00114 MarkMemoryUsage(bool verb = false)
00115 {
00116 mMemUseMark = mMemUse;
00117 mNrAllocMark = mNrAlloc;
00118 mNrDeallocMark = mNrDealloc;
00119 if (verb)
00120 {
00121 String b = Process::MemoryInfo::Bytes2String(mMemUse);
00122 ILOG_INFO("Marking memory usage: " << mMemUse << " (" << b << ")"
00123 << ", nr alloc: " << mNrAlloc
00124 << ", nr dealloc: " << mNrDealloc);
00125 DumpMap();
00126 }
00127 }
00128
00129 Int64
00130 MemoryUsageSinceMark(bool verb = false) const
00131 {
00132 Int64 memUseSinceMark = mMemUse - mMemUseMark;
00133 String b1 = Process::MemoryInfo::Bytes2String(mMemUse - mMemUseMark);
00134 String b2 = Process::MemoryInfo::Bytes2String(mMemUse);
00135 if (verb)
00136 {
00137 ILOG_INFO("Memory usage since last mark: " << memUseSinceMark
00138 << " (" << b1 << ")"
00139 << ", nr alloc: " << NrAllocMark()
00140 << ", nr dealloc: " << NrDeallocMark()
00141 << ", alloc usage: " << AllocUsageMark());
00142 ILOG_INFO(" total memory usage: " << mMemUse
00143 << " (" << b2 << ")"
00144 << ", nr alloc: " << mNrAlloc
00145 << ", nr dealloc: " << mNrDealloc
00146 << ", alloc usage: " << mNrAlloc - mNrDealloc);
00147 DumpMap();
00148 }
00149 return memUseSinceMark;
00150 }
00151
00152 void
00153 CheckMemoryUsageSinceMark(bool verb = false) const
00154 {
00155 Int64 memUseSinceMark = MemoryUsageSinceMark(verb);
00156 if (memUseSinceMark > 0)
00157 {
00158 String b = Process::MemoryInfo::Bytes2String(memUseSinceMark);
00159 ILOG_INFO("Memory usage increased since last mark by: " <<
00160 memUseSinceMark << " (" << b << "), alloc usage by: " <<
00161 AllocUsageMark());
00162 }
00163 }
00164
00165 int
00166 AllocUsageMark() const
00167 {
00168 return NrAllocMark() - NrDeallocMark();
00169 }
00170
00171 int
00172 NrAllocMark() const
00173 {
00174 return mNrAlloc - mNrAllocMark;
00175 }
00176
00177 int
00178 NrDeallocMark() const
00179 {
00180 return mNrDealloc - mNrDeallocMark;
00181 }
00182
00183 void
00184 DumpMap() const
00185 {
00186 ILOG_INFO("DumpMap start");
00187 for (SysInfMap::const_iterator i=mMap.begin() ; i!=mMap.end() ; i++)
00188 ILOG_INFO(i->second.mAllocNr << " = (0x" << i->first << ") "
00189 << i->second.mN << " elements of " << i->second.mSizeof
00190 << " bytes");
00191 ILOG_INFO("DumpMap end");
00192 }
00193
00194 private:
00195
00196 class SysInf
00197 {
00198 public:
00199 SysInf()
00200 {
00201 }
00202
00203 SysInf(size_t n, size_t siz, int al)
00204 {
00205 mN = n;
00206 mSizeof = siz;
00207 mAllocNr = al;
00208 }
00209
00210 size_t mN;
00211 size_t mSizeof;
00212 int mAllocNr;
00213 };
00214
00215 typedef std::map<void*,SysInf> SysInfMap;
00216
00217 SysInfMap mMap;
00218
00219 ArraySystem()
00220 {
00221 mMemUse = 0;
00222 mMemUseMark = 0;
00223 mNrAlloc = 0;
00224 mNrDealloc = 0;
00225 mNrAllocMark = 0;
00226 mNrDeallocMark = 0;
00227 }
00228
00229 ArraySystem(const ArraySystem&)
00230 {
00231 }
00232
00233 ArraySystem&
00234 operator=(const ArraySystem&);
00235
00236 size_t mMemUse;
00237 size_t mMemUseMark;
00238 int mNrAlloc;
00239 int mNrDealloc;
00240 int mNrAllocMark;
00241 int mNrDeallocMark;
00242
00243 ILOG_VAR_DEC;
00244
00245 };
00246
00247 ILOG_VAR_INIT(ArraySystem, Impala.Core.Array);
00248
00249 }
00250 }
00251 }
00252
00253 #endif