MemoryManager.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #ifndef _MemoryManager_h_
  2. #define _MemoryManager_h_
  3. #include "CoreBase.h"
  4. //#define MM_NO_DEBUGMEMORY
  5. //#define MM_FILL_MEMORY
  6. #define MM_MEMORY_FILLER 0xff
  7. //#define MM_MEMORY_FILLER 0x7f
  8. #define MemoryManagerMemoryBlockSize 4 //x*4, x >= 1
  9. class MemoryManager
  10. {
  11. struct GuardBlock
  12. {
  13. dword guard[MemoryManagerMemoryBlockSize - 1];
  14. __forceinline bool operator == (const GuardBlock & b)
  15. {
  16. for(long i = 0; i < sizeof(guard)/sizeof(guard[0]); i++)
  17. {
  18. if(guard[i] != b.guard[i]) return false;
  19. }
  20. return true;
  21. }
  22. };
  23. struct MemoryBlock
  24. {
  25. long descIndex; //Индекс описывающего блока (дескриптора)
  26. GuardBlock openGuardBlock; //Защищающий код
  27. };
  28. struct MemoryBlockDesc
  29. {
  30. MemoryBlock * block; //Указатель на блок памяти
  31. dword blockSize; //Размер блока памяти (без данных менеджера)
  32. long descIndex; //Индекс идентификатора места аллокации
  33. };
  34. struct DescString
  35. {
  36. long next; //Индекс следующего блока
  37. const char * fileNamePtr; //Указатель на исходную строку
  38. long fileLine; //Общее количество алоцированных блоков за всё время
  39. dword numAllocBlocks; //Общее количество алоцированных блоков за всё время
  40. bool isUse; //Флаг для подсчёта алокаций
  41. char fileName[1]; //Сохранённая строка
  42. };
  43. class IMemoryPool
  44. {
  45. public:
  46. virtual ~IMemoryPool(){};
  47. //Выделить память данного размера
  48. virtual void * Alloc() = null;
  49. //Попытаться освободить память
  50. virtual bool Free(void * ptr) = null;
  51. //Получить размер блока по адресу
  52. virtual dword GetSize(void * ptr) = null;
  53. };
  54. template<int Size> class MemoryPool : public IMemoryPool
  55. {
  56. //Описание одного блока
  57. struct Block
  58. {
  59. dword use[(4096/Size + 31)/32];
  60. byte pool[4096/Size][Size];
  61. };
  62. public:
  63. MemoryPool();
  64. ~MemoryPool();
  65. //Выделить память данного размера
  66. virtual void * Alloc();
  67. //Попытаться освободить память
  68. virtual bool Free(void * ptr);
  69. //Получить размер блока по адресу
  70. virtual dword GetSize(void * ptr);
  71. private:
  72. //Добавить адрес в общий диапазон
  73. void * AddAddress(void * ptr);
  74. private:
  75. void * minAddr; //Минимальный используемый адрес
  76. void * maxAddr; //Минимальный используемый адрес
  77. Block ** blocks; //Выделенные блоки
  78. dword blocksCount; //Количество блоков
  79. dword blocksMax; //Размер массива для блоков
  80. };
  81. class MemoryPools
  82. {
  83. public:
  84. MemoryPools();
  85. void * Alloc(dword size);
  86. bool Free(void * ptr);
  87. dword Size(void * ptr);
  88. private:
  89. IMemoryPool * pools[24];
  90. void * minAddr;
  91. void * maxAddr;
  92. MemoryPool<4> pool4; MemoryPool<8> pool8; MemoryPool<12> pool12; MemoryPool<16> pool16;
  93. MemoryPool<20> pool20; MemoryPool<24> pool24; MemoryPool<28> pool28; MemoryPool<32> pool32;
  94. MemoryPool<36> pool36; MemoryPool<40> pool40; MemoryPool<44> pool44; MemoryPool<48> pool48;
  95. MemoryPool<52> pool52; MemoryPool<56> pool56; MemoryPool<60> pool60; MemoryPool<64> pool64;
  96. MemoryPool<68> pool68; MemoryPool<72> pool72; MemoryPool<76> pool76; MemoryPool<80> pool80;
  97. MemoryPool<84> pool84; MemoryPool<88> pool88; MemoryPool<92> pool92; MemoryPool<96> pool96;
  98. };
  99. template<int Size> friend class MemoryPool;
  100. struct StatData
  101. {
  102. long descIndex;
  103. dword blocksCount;
  104. dword totalSize;
  105. dword totalAllocs;
  106. };
  107. public:
  108. MemoryManager();
  109. ~MemoryManager();
  110. void ReleaseMemory(bool enableLogout);
  111. //-------------------------------------------------------------------------------------------------------
  112. //Работа с менеджером памяти
  113. //-------------------------------------------------------------------------------------------------------
  114. public:
  115. CritSection coreSection;
  116. //Выделить или изменить объём выделеной памяти
  117. void * Reallocate(void * ptr, dword size, const char * fileName, long fileLine);
  118. //Освободить память
  119. void Free(void * ptr, const char * fileName, long fileLine);
  120. //Освободить всю память
  121. void FreeMemory();
  122. //Вывести в лог статистику
  123. void TraceStatistic(CoreCommand_MemStat & stats);
  124. //Посчитать статистику по запросу
  125. void GetStatistic(CoreCommand_GetMemStat & stats);
  126. //Посчитать память занимаемую отладочной информацией менеджера
  127. void GetManagerStat(CoreCommand_GetMemManagerStat & stats);
  128. private:
  129. static bool TraceStat_SortBySize(const StatData & d1, const StatData & d2);
  130. static bool TraceStat_SortByBlocks(const StatData & d1, const StatData & d2);
  131. static bool TraceStat_SortByFreq(const StatData & d1, const StatData & d2);
  132. static bool TraceStat_SortByFiles(const StatData & d1, const StatData & d2);
  133. public:
  134. //Режим панической проверки
  135. void SetPanicCheckMemoryMode(bool isSet);
  136. //Стоит ли режим панической проверки
  137. bool IsPanicCheckMemoryMode();
  138. //Запустить - остоновить усиленную проверку памяти
  139. void EnablePanicCheckMemory(bool isEnable);
  140. //Включить пулы памяти
  141. void EnableMemPools();
  142. //Включены ли пулы памяти
  143. bool IsEnableMemPools();
  144. //Обновить состояние мэнеджера
  145. void Update();
  146. //Проверить на целостность всю выделенную память
  147. void PanicCheckMemory();
  148. //Сделать плановую проверку
  149. void CheckMemoryStep();
  150. //-------------------------------------------------------------------------------------------------------
  151. //Внутреннии незащищёные критическими секциями функции
  152. //-------------------------------------------------------------------------------------------------------
  153. private:
  154. //Проверить на целостность всю выделенную память
  155. void SysPanicCheckMemory();
  156. //-------------------------------------------------------------------------------------------------------
  157. //Работа с памятью менеджера
  158. //-------------------------------------------------------------------------------------------------------
  159. private:
  160. //Выделить память в пуле
  161. void * PoolAlloc(dword size, void * ptr, const char * fileName, long fileLine);
  162. //Освободить память в пуле
  163. bool PoolFree(void * ptr);
  164. //Выделить память вне пула
  165. void * MemAlloc(dword size, void * ptr, const char * fileName, long fileLine);
  166. //Освободить память
  167. void FreeInternal(void * ptr);
  168. //Проверить блок памяти
  169. void _fastcall CheckBlock(MemoryBlock * block);
  170. //Проверить на валидность поинтер
  171. bool IsValidateBlockPointer(MemoryBlock * block);
  172. //Проверить все блоки и вывести всю доступнукю информацию по разрушеным блокам
  173. void TraceDamagedBlocks();
  174. //Получить индекс строки
  175. long GetStringDescIndex(const char * fileName, long fileLine);
  176. //-------------------------------------------------------------------------------------------------------
  177. //Работа с системной памятью
  178. //-------------------------------------------------------------------------------------------------------
  179. private:
  180. //Выделить системную память
  181. static void * SysAlloc(dword size, void * ptr = null);
  182. //Освободить системную память
  183. static void SysFree(void * ptr);
  184. //Получить размер системного блока
  185. static dword SysSize(void * ptr);
  186. //-------------------------------------------------------------------------------------------------------
  187. private:
  188. ClassThread
  189. private:
  190. #ifndef MM_NO_DEBUGMEMORY
  191. //Таблицы описаний
  192. MemoryBlockDesc * descs; //Массив опиcаний блоков
  193. long descsCount; //Количество блоков (описаний)
  194. long descsMax; //Размер массива
  195. long currentCheck; //Индекс текущего проверяемого блока
  196. char * strings; //Строки
  197. dword stringsSize; //Размер используемой части буфера строк
  198. dword stringsMax; //Размер буфера строк
  199. long entry[1024]; //Входная таблица для поиска строки
  200. bool isMemCheck; //Проверять на целостность память в фоновом режиме
  201. bool isPanicCheck; //Проверять на целостность всю память на каждом кадре и каждом запросе
  202. bool isPanicCheckEnable; //Запустить-остановить паническую проверку
  203. GuardBlock openBlock; //Открывающий блок
  204. GuardBlock closeBlock; //Закрывающий блок
  205. #endif
  206. bool isPoolEnable; //Разрешена система сбора мелких блоков
  207. const char * lastFileName; //Имя файла, где выделялась память в последний раз
  208. long lastFileLine; //Линия в файле, где выделялась память в последний раз
  209. MemoryPools pools; //Пулы памяти
  210. static dword totalSize; //Выделенной в системе памяти
  211. static dword totalBlocks; //Всего выделенно блоков
  212. static dword maxBlocks; //Максимальное выделенное количество блоков в системе
  213. static dword maxPoolBlocks; //Максимальное выделенное количество блоков в пулах
  214. static dword maxSize; //Максимальное выделенное количество памяти в системе
  215. static dword poolBlocks; //Блоков выделеных в пуле
  216. static dword allocsPerFrame; //Алокаций за кадр
  217. static dword deletesPerFrame; //Удалений за кадр
  218. static dword maxUsed360; //Пик используемой памяти на xbox
  219. //
  220. static dword emptyMemory; //Память для блоков 0 размера
  221. static const char * line;
  222. };
  223. #endif