Panda3D

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   virtual void mark_pointer(void *ptr, size_t orig_size, ReferenceCount *ref_ptr);
00054 
00055 #if (defined(WIN32_VC) || defined(WIN64_VC)) && defined(_DEBUG)
00056   static int win32_malloc_hook(int alloc_type, void *ptr, 
00057                                size_t size, int block_use, long request, 
00058                                const unsigned char *filename, int line);
00059 #endif
00060     
00061 PUBLISHED:
00062   INLINE static bool is_tracking();
00063   INLINE static bool is_counting();
00064   INLINE static size_t get_current_cpp_size();
00065   INLINE static size_t get_total_cpp_size();
00066 
00067   INLINE static size_t get_panda_heap_single_size();
00068   INLINE static size_t get_panda_heap_array_size();
00069   INLINE static size_t get_panda_heap_overhead();
00070   INLINE static size_t get_panda_mmap_size();
00071   INLINE static size_t get_external_size();
00072   INLINE static size_t get_total_size();
00073 
00074   INLINE static int get_num_pointers();
00075   INLINE static void get_pointers(MemoryUsagePointers &result);
00076   INLINE static void get_pointers_of_type(MemoryUsagePointers &result,
00077                                           TypeHandle type);
00078   INLINE static void get_pointers_of_age(MemoryUsagePointers &result,
00079                                          double from, double to);
00080   INLINE static void get_pointers_with_zero_count(MemoryUsagePointers &result);
00081 
00082   INLINE static void freeze();
00083 
00084   INLINE static void show_current_types();
00085   INLINE static void show_trend_types();
00086   INLINE static void show_current_ages();
00087   INLINE static void show_trend_ages();
00088 
00089 protected:
00090   virtual void overflow_heap_size();
00091 
00092 private:
00093   MemoryUsage(const MemoryHook &copy);
00094   static MemoryUsage *get_global_ptr();
00095 
00096   void ns_record_pointer(ReferenceCount *ptr);
00097   void ns_update_type(ReferenceCount *ptr, TypeHandle type);
00098   void ns_update_type(ReferenceCount *ptr, TypedObject *typed_ptr);
00099   void ns_remove_pointer(ReferenceCount *ptr);
00100 
00101   void ns_record_void_pointer(void *ptr, size_t size);
00102   void ns_remove_void_pointer(void *ptr);
00103 
00104   size_t ns_get_total_size();
00105   int ns_get_num_pointers();
00106   void ns_get_pointers(MemoryUsagePointers &result);
00107   void ns_get_pointers_of_type(MemoryUsagePointers &result,
00108                                TypeHandle type);
00109   void ns_get_pointers_of_age(MemoryUsagePointers &result,
00110                               double from, double to);
00111   void ns_get_pointers_with_zero_count(MemoryUsagePointers &result);
00112   void ns_freeze();
00113 
00114   void ns_show_current_types();
00115   void ns_show_trend_types();
00116   void ns_show_current_ages();
00117   void ns_show_trend_ages();
00118 
00119   void consolidate_void_ptr(MemoryInfo *info);
00120   void refresh_info_set();
00121 
00122   static MemoryUsage *_global_ptr;
00123 
00124   // We shouldn't use a pmap, since that would be recursive!
00125   // Actually, it turns out that it doesn't matter, since somehow the
00126   // pallocator gets used even though we don't specify it here, so we
00127   // have to make special code that handles the recursion anyway.
00128 
00129   // This table stores up to two entiries for each MemoryInfo object:
00130   // one for the void pointer (the pointer to the beginning of the
00131   // allocated memory block), and one for the ReferenceCount pointer.
00132   // For a particular object, these two pointers may be the same or
00133   // they may be different.  Some objects may be stored under both
00134   // pointers, while others may be stored under only one pointer or
00135   // the other.  We don't store an entry for an object's TypedObject
00136   // pointer.
00137   typedef map<void *, MemoryInfo *> Table;
00138   Table _table;
00139 
00140   // This table indexes the individual MemoryInfo objects, for unique
00141   // iteration.
00142   typedef set<MemoryInfo *> InfoSet;
00143   InfoSet _info_set;
00144   bool _info_set_dirty;
00145 
00146   int _freeze_index;
00147   int _count;
00148   size_t _current_cpp_size;
00149   size_t _total_cpp_size;
00150   size_t _total_size;
00151 
00152   class TypeHistogram {
00153   public:
00154     void add_info(TypeHandle type, MemoryInfo *info);
00155     void show() const;
00156     void clear();
00157 
00158   private:
00159     // Cannot use a pmap, since that would be recursive!
00160     typedef map<TypeHandle, MemoryUsagePointerCounts> Counts;
00161     Counts _counts;
00162   };
00163   TypeHistogram _trend_types;
00164 
00165   class AgeHistogram {
00166   public:
00167     AgeHistogram();
00168     void add_info(double age, MemoryInfo *info);
00169     void show() const;
00170     void clear();
00171 
00172   private:
00173     int choose_bucket(double age) const;
00174 
00175     enum { num_buckets = 5 };
00176     MemoryUsagePointerCounts _counts[num_buckets];
00177     static double _cutoff[num_buckets];
00178   };
00179   AgeHistogram _trend_ages;
00180 
00181 
00182   bool _track_memory_usage;
00183   bool _startup_track_memory_usage;
00184   bool _count_memory_usage;
00185   bool _report_memory_usage;
00186   double _report_memory_interval;
00187   double _last_report_time;
00188 
00189   static bool _recursion_protect;
00190 };
00191 
00192 #include "memoryUsage.I"
00193 
00194 #endif  // DO_MEMORY_USAGE
00195 
00196 #endif
00197 
 All Classes Functions Variables Enumerations