Panda3D
 All Classes Functions Variables Enumerations
memoryUsage.h
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 &copy);
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 
 All Classes Functions Variables Enumerations