Panda3D
|
00001 // Filename: memoryUsage.h 00002 // Created by: drose (25May00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef MEMORYUSAGE_H 00016 #define MEMORYUSAGE_H 00017 00018 #include "pandabase.h" 00019 00020 #ifdef DO_MEMORY_USAGE 00021 00022 #include "typedObject.h" 00023 #include "memoryInfo.h" 00024 #include "memoryUsagePointerCounts.h" 00025 #include "pmap.h" 00026 #include "memoryHook.h" 00027 00028 class ReferenceCount; 00029 class MemoryUsagePointers; 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Class : MemoryUsage 00033 // Description : This class is used strictly for debugging purposes, 00034 // specifically for tracking memory leaks of 00035 // reference-counted objects: it keeps a record of every 00036 // such object currently allocated. 00037 // 00038 // When compiled with NDEBUG set, this entire class does 00039 // nothing and compiles to nothing. 00040 //////////////////////////////////////////////////////////////////// 00041 class EXPCL_PANDAEXPRESS MemoryUsage : public MemoryHook { 00042 public: 00043 INLINE static bool get_track_memory_usage(); 00044 00045 INLINE static void record_pointer(ReferenceCount *ptr); 00046 INLINE static void update_type(ReferenceCount *ptr, TypeHandle type); 00047 INLINE static void update_type(ReferenceCount *ptr, TypedObject *typed_ptr); 00048 INLINE static void remove_pointer(ReferenceCount *ptr); 00049 00050 public: 00051 virtual void *heap_alloc_single(size_t size); 00052 virtual void heap_free_single(void *ptr); 00053 00054 virtual void *heap_alloc_array(size_t size); 00055 virtual void *heap_realloc_array(void *ptr, size_t size); 00056 virtual void heap_free_array(void *ptr); 00057 00058 virtual void mark_pointer(void *ptr, size_t orig_size, ReferenceCount *ref_ptr); 00059 00060 #if (defined(WIN32_VC) || defined(WIN64_VC)) && defined(_DEBUG) 00061 static int win32_malloc_hook(int alloc_type, void *ptr, 00062 size_t size, int block_use, long request, 00063 const unsigned char *filename, int line); 00064 #endif 00065 00066 PUBLISHED: 00067 INLINE static bool is_tracking(); 00068 INLINE static bool is_counting(); 00069 INLINE static size_t get_current_cpp_size(); 00070 INLINE static size_t get_total_cpp_size(); 00071 00072 INLINE static size_t get_panda_heap_single_size(); 00073 INLINE static size_t get_panda_heap_array_size(); 00074 INLINE static size_t get_panda_heap_overhead(); 00075 INLINE static size_t get_panda_mmap_size(); 00076 INLINE static size_t get_external_size(); 00077 INLINE static size_t get_total_size(); 00078 00079 INLINE static int get_num_pointers(); 00080 INLINE static void get_pointers(MemoryUsagePointers &result); 00081 INLINE static void get_pointers_of_type(MemoryUsagePointers &result, 00082 TypeHandle type); 00083 INLINE static void get_pointers_of_age(MemoryUsagePointers &result, 00084 double from, double to); 00085 INLINE static void get_pointers_with_zero_count(MemoryUsagePointers &result); 00086 00087 INLINE static void freeze(); 00088 00089 INLINE static void show_current_types(); 00090 INLINE static void show_trend_types(); 00091 INLINE static void show_current_ages(); 00092 INLINE static void show_trend_ages(); 00093 00094 protected: 00095 virtual void overflow_heap_size(); 00096 00097 private: 00098 MemoryUsage(const MemoryHook ©); 00099 static MemoryUsage *get_global_ptr(); 00100 00101 void ns_record_pointer(ReferenceCount *ptr); 00102 void ns_update_type(ReferenceCount *ptr, TypeHandle type); 00103 void ns_update_type(ReferenceCount *ptr, TypedObject *typed_ptr); 00104 void ns_remove_pointer(ReferenceCount *ptr); 00105 00106 void ns_record_void_pointer(void *ptr, size_t size); 00107 void ns_remove_void_pointer(void *ptr); 00108 00109 size_t ns_get_total_size(); 00110 int ns_get_num_pointers(); 00111 void ns_get_pointers(MemoryUsagePointers &result); 00112 void ns_get_pointers_of_type(MemoryUsagePointers &result, 00113 TypeHandle type); 00114 void ns_get_pointers_of_age(MemoryUsagePointers &result, 00115 double from, double to); 00116 void ns_get_pointers_with_zero_count(MemoryUsagePointers &result); 00117 void ns_freeze(); 00118 00119 void ns_show_current_types(); 00120 void ns_show_trend_types(); 00121 void ns_show_current_ages(); 00122 void ns_show_trend_ages(); 00123 00124 void consolidate_void_ptr(MemoryInfo *info); 00125 void refresh_info_set(); 00126 00127 static MemoryUsage *_global_ptr; 00128 00129 // We shouldn't use a pmap, since that would be recursive! 00130 // Actually, it turns out that it doesn't matter, since somehow the 00131 // pallocator gets used even though we don't specify it here, so we 00132 // have to make special code that handles the recursion anyway. 00133 00134 // This table stores up to two entiries for each MemoryInfo object: 00135 // one for the void pointer (the pointer to the beginning of the 00136 // allocated memory block), and one for the ReferenceCount pointer. 00137 // For a particular object, these two pointers may be the same or 00138 // they may be different. Some objects may be stored under both 00139 // pointers, while others may be stored under only one pointer or 00140 // the other. We don't store an entry for an object's TypedObject 00141 // pointer. 00142 typedef map<void *, MemoryInfo *> Table; 00143 Table _table; 00144 00145 // This table indexes the individual MemoryInfo objects, for unique 00146 // iteration. 00147 typedef set<MemoryInfo *> InfoSet; 00148 InfoSet _info_set; 00149 bool _info_set_dirty; 00150 00151 int _freeze_index; 00152 int _count; 00153 size_t _current_cpp_size; 00154 size_t _total_cpp_size; 00155 size_t _total_size; 00156 00157 class TypeHistogram { 00158 public: 00159 void add_info(TypeHandle type, MemoryInfo *info); 00160 void show() const; 00161 void clear(); 00162 00163 private: 00164 // Cannot use a pmap, since that would be recursive! 00165 typedef map<TypeHandle, MemoryUsagePointerCounts> Counts; 00166 Counts _counts; 00167 }; 00168 TypeHistogram _trend_types; 00169 00170 class AgeHistogram { 00171 public: 00172 AgeHistogram(); 00173 void add_info(double age, MemoryInfo *info); 00174 void show() const; 00175 void clear(); 00176 00177 private: 00178 int choose_bucket(double age) const; 00179 00180 enum { num_buckets = 5 }; 00181 MemoryUsagePointerCounts _counts[num_buckets]; 00182 static double _cutoff[num_buckets]; 00183 }; 00184 AgeHistogram _trend_ages; 00185 00186 00187 bool _track_memory_usage; 00188 bool _startup_track_memory_usage; 00189 bool _count_memory_usage; 00190 bool _report_memory_usage; 00191 double _report_memory_interval; 00192 double _last_report_time; 00193 00194 static bool _recursion_protect; 00195 }; 00196 00197 #include "memoryUsage.I" 00198 00199 #endif // DO_MEMORY_USAGE 00200 00201 #endif 00202