00001 #include "memhist.h"
00002
00008 #ifndef DOXYGEN
00009
00010 #include <istream>
00011 #include <ostream>
00012 #include <cassert>
00013 #include <iostream>
00014 using namespace std;
00015
00016 MemoryEvent::MemoryEvent(void *ptr,size_t size)
00017 : _ptr(ptr), _size(size), _new(true)
00018 {
00019 }
00020
00021 MemoryEvent::MemoryEvent(void *ptr)
00022 : _ptr(ptr), _size(0), _new(false)
00023 {
00024 }
00025
00026 MemoryEventHistory::MemoryEventHistory()
00027 {
00028 }
00029
00030 MemoryEventHistory::MemoryEventHistory(istream &is)
00031 {
00032 char type;
00033 void *ptr;
00034 size_t size;
00035
00036 while (is.good())
00037 {
00038 is >> type;
00039
00040 if (type=='+')
00041 {
00042 is >> ptr >> size;
00043 push_back(MemoryEvent(ptr,size));
00044 }
00045
00046 if (type=='-')
00047 {
00048 is >> ptr;
00049 push_back(MemoryEvent(ptr));
00050 }
00051
00052 type = 0;
00053 }
00054 }
00055
00056 void
00057 MemoryEventHistory::summary(ostream &os) const
00058 {
00059 MemoryModel mem;
00060 for (list<MemoryEvent>::const_iterator i=begin(); i!=end(); i++)
00061 mem.apply(*i);
00062
00063 os << "Address space: " << (void *) mem.minAddress() << " - " << (void *) mem.maxAddress() << endl;
00064 os << "Peak memory : " << mem.maxMemory() << " bytes in " << mem.maxBlocks() << " blocks." << endl;
00065 os << "Used memory : " << mem.memoryUsed() << " bytes in " << mem.blocks() << " blocks." << endl;
00066 os << "Allocations : " << mem.numAllocations() << " blocks." << endl;
00067 os << "Releases : " << mem.numFree() << " blocks, " << mem.numFreeNull() << " NULL, " << mem.numFreeInvalid() << " invalid." << endl;
00068 }
00069
00071
00072 MemoryModel::MemoryModel()
00073 : _memoryUsed(0),
00074 _minAddress(0xffffffff),
00075 _maxAddress(0x00000000),
00076 _maxBlocks(0),
00077 _maxMemory(0),
00078 _numAllocations(0),
00079 _numFree(0),
00080 _numFreeNull(0),
00081 _numFreeInvalid(0)
00082 {
00083 }
00084
00085 void
00086 MemoryModel::apply(const MemoryEvent &event)
00087 {
00088 const size_t min = size_t(event._ptr);
00089 const size_t max = min + event._size;
00090
00091 if (event._new)
00092 {
00093 assert(_allocated.find(min)==_allocated.end());
00094
00095 _allocated.insert(make_pair(min,max));
00096 _memoryUsed += event._size;
00097 if (min<_minAddress) { _minAddress = min; _maxBlocks = blocks(); }
00098 if (max>_maxAddress) { _maxAddress = max; _maxBlocks = blocks(); }
00099 if (_memoryUsed>_maxMemory) { _maxMemory = _memoryUsed; }
00100 _numAllocations++;
00101 }
00102 else
00103 {
00104 _numFree++;
00105
00106 if (min==0)
00107 {
00108 _numFreeNull++;
00109 return;
00110 }
00111
00112 std::map<size_t, size_t, std::less<size_t> >::iterator i = _allocated.find(min);
00113 if (i!=_allocated.end())
00114 {
00115 _memoryUsed -= i->second - i->first;
00116 _allocated.erase(i);
00117
00118 assert(_allocated.find(min)==_allocated.end());
00119 }
00120 else
00121 {
00122 cout << (void *) min << endl;
00123 _numFreeInvalid++;
00124 }
00125
00126 return;
00127 }
00128 }
00129
00130 size_t MemoryModel::minAddress() const { return _minAddress; }
00131 size_t MemoryModel::maxAddress() const { return _maxAddress; }
00132 size_t MemoryModel::addressSpace() const { return _maxAddress - _minAddress; }
00133 size_t MemoryModel::blocks() const { return _allocated.size(); }
00134 size_t MemoryModel::memoryUsed() const { return _memoryUsed; }
00135 size_t MemoryModel::maxBlocks() const { return _maxBlocks; }
00136 size_t MemoryModel::maxMemory() const { return _maxMemory; }
00137
00138 size_t MemoryModel::numAllocations() const { return _numAllocations; }
00139 size_t MemoryModel::numFree() const { return _numFree; }
00140 size_t MemoryModel::numFreeNull() const { return _numFreeNull; }
00141 size_t MemoryModel::numFreeInvalid() const { return _numFreeInvalid; }
00142
00143 #endif