2
0
David Rose 24 жил өмнө
parent
commit
62ccc44d39

+ 5 - 0
panda/src/express/memoryInfo.cxx

@@ -20,6 +20,9 @@
 #include "typedReferenceCount.h"
 #include "typeHandle.h"
 
+#ifndef NDEBUG
+// Nothing in this module gets compiled in NDEBUG mode.
+
 ////////////////////////////////////////////////////////////////////
 //     Function: MemoryInfo::Constructor
 //       Access: Public
@@ -147,3 +150,5 @@ update_type_handle(TypeHandle &destination, TypeHandle refined) {
     destination = refined;
   }
 }
+
+#endif  // NDEBUG

+ 66 - 6
panda/src/express/memoryUsage.I

@@ -128,21 +128,81 @@ is_tracking() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: MemoryUsage::get_allocated_size
+//     Function: MemoryUsage::is_counting
+//       Access: Public, Static
+//  Description: Returns true if the MemoryUsage object is currently
+//               at least counting memory (e.g. count-memory-usage is
+//               configured #t), even if it's not fully tracking it.
+////////////////////////////////////////////////////////////////////
+INLINE bool MemoryUsage::
+is_counting() {
+  return get_global_ptr()->_count_memory_usage;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryUsage::get_current_cpp_size
 //       Access: Public, Static
 //  Description: Returns the total number of bytes of allocated memory
-//               as counted, excluding the memory previously frozen.
+//               via the C++ operators new and delete as counted,
+//               not including the memory previously frozen.
 ////////////////////////////////////////////////////////////////////
 INLINE size_t MemoryUsage::
-get_allocated_size() {
-  return get_global_ptr()->ns_get_allocated_size();
+get_current_cpp_size() {
+  return get_global_ptr()->ns_get_current_cpp_size();
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: MemoryUsage::get_total_size
+//     Function: MemoryUsage::has_cpp_size
+//       Access: Public, Static
+//  Description: Returns true if the value returned by
+//               get_cpp_size() is meaningful on this particular
+//               system with this particular configuration, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool MemoryUsage::
+has_cpp_size() {
+  return is_tracking();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryUsage::get_cpp_size
 //       Access: Public, Static
 //  Description: Returns the total number of bytes of allocated memory
-//               as counted, including the memory previously frozen.
+//               via the C++ operators new and delete as counted,
+//               including the memory previously frozen.
+////////////////////////////////////////////////////////////////////
+INLINE size_t MemoryUsage::
+get_cpp_size() {
+  return get_global_ptr()->ns_get_cpp_size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryUsage::has_total_size
+//       Access: Public, Static
+//  Description: Returns true if the value returned by
+//               get_total_size() is meaningful on this particular
+//               system with this particular configuration, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool MemoryUsage::
+has_total_size() {
+#if defined(WIN32_VC) && defined(_DEBUG)
+  // Windows in debug mode can count total size without having to do a
+  // full track.
+  return is_counting();
+#else
+  // Other systems require the full hammer.
+  return is_tracking();
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryUsage::get_total_size
+//       Access: Public, Static
+//  Description: Returns the total size of the dynamic heap, as nearly
+//               as can be determined, including all allocated memory
+//               if possible, in addition to that tracked by
+//               get_cpp_size().
 ////////////////////////////////////////////////////////////////////
 INLINE size_t MemoryUsage::
 get_total_size() {

+ 96 - 22
panda/src/express/memoryUsage.cxx

@@ -29,6 +29,9 @@
 #endif
 
 #include "memoryUsage.h"
+#if defined(WIN32_VC) && defined(_DEBUG)
+#include <crtdbg.h>
+#endif
 
 #ifndef NDEBUG
 // Nothing in this module gets compiled in NDEBUG mode.
@@ -273,6 +276,42 @@ operator_delete_handler(void *ptr) {
   default_operator_delete(ptr);
 }
 
+#if defined(WIN32_VC) && defined(_DEBUG)
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryUsage::win32_malloc_hook
+//       Access: Public, Static
+//  Description: This callback is attached to the Win32 debug malloc
+//               system to be called whenever a pointer is allocated,
+//               reallocated, or freed.  It's used to track the total
+//               memory allocated via calls to malloc().
+////////////////////////////////////////////////////////////////////
+int MemoryUsage::
+win32_malloc_hook(int alloc_type, void *ptr, 
+                  size_t size, int block_use, long request, 
+                  const unsigned char *filename, int line) {
+  MemoryUsage *mu = get_global_ptr();
+  if (mu->_count_memory_usage) {
+    switch (alloc_type) {
+    case _HOOK_ALLOC:
+      mu->_total_size += size;
+      break;
+      
+    case _HOOK_REALLOC:
+      mu->_total_size += size - _msize(ptr);
+      break;
+      
+    case _HOOK_FREE:
+      mu->_total_size -= _msize(ptr);
+      break;
+    }
+  }
+
+  return true;
+}
+#endif  // WIN32_VC && _DEBUG
+
+
+
 ////////////////////////////////////////////////////////////////////
 //     Function: MemoryUsage::Constructor
 //       Access: Private
@@ -280,12 +319,27 @@ operator_delete_handler(void *ptr) {
 ////////////////////////////////////////////////////////////////////
 MemoryUsage::
 MemoryUsage() {
-  // We must get this here instead of in config_express.cxx, because we
-  // need to know it at static init time, and who knows when the code
-  // in config_express will be executed.
+  // We must get these variables here instead of in
+  // config_express.cxx, because we need to know it at static init
+  // time, and who knows when the code in config_express will be
+  // executed.
+
+  // track-memory-usage should be true to enable full-force tracking
+  // of C++ allocations and recordkeeping by type.  It's quite
+  // expensive.
   _track_memory_usage =
     config_express.GetBool("track-memory-usage", false);
 
+  // count-memory-usage is a much lighter-weight version, and only
+  // tracks the total memory allocation.  However, it only works for
+  // certain build environments.
+#if defined(WIN32_VC) && defined(_DEBUG)
+  _count_memory_usage =
+    config_express.GetBool("count-memory-usage", true);
+#else
+  _count_memory_usage = false;
+#endif
+
   if (_track_memory_usage) {
     // Redefine the global pointers for operator new and operator
     // delete (these pointers are defined up in DTOOL) to vector into
@@ -294,9 +348,16 @@ MemoryUsage() {
     global_operator_delete = &operator_delete_handler;
   }
 
+#if defined(WIN32_VC) && defined(_DEBUG)
+  if (_count_memory_usage) {
+    _CrtSetAllocHook(&win32_malloc_hook);
+  }
+#endif
+
   _freeze_index = 0;
   _count = 0;
-  _allocated_size = 0;
+  _current_cpp_size = 0;
+  _cpp_size = 0;
   _total_size = 0;
 }
 
@@ -467,9 +528,9 @@ ns_remove_pointer(ReferenceCount *ptr) {
       // pointer, remove it from the table.
       if (info._freeze_index == _freeze_index) {
         _count--;
-        _allocated_size -= info._size;
+        _current_cpp_size -= info._size;
       }
-      _total_size -= info._size;
+      _cpp_size -= info._size;
 
       // We have to protect modifications to the table from recursive
       // calls by turning off _track_memory_usage while we adjust it.
@@ -513,11 +574,11 @@ ns_record_void_pointer(void *ptr, size_t size) {
     }
 
     if (info._freeze_index == _freeze_index) {
-      _allocated_size += size - info._size;
+      _current_cpp_size += size - info._size;
     } else {
-      _allocated_size += size;
+      _current_cpp_size += size;
     }
-    _total_size += size - info._size;
+    _cpp_size += size - info._size;
 
     info._void_ptr = ptr;
     info._size = size;
@@ -570,9 +631,9 @@ ns_remove_void_pointer(void *ptr) {
 
       if (info._freeze_index == _freeze_index) {
         _count--;
-        _allocated_size -= info._size;
+        _current_cpp_size -= info._size;
       }
-      _total_size -= info._size;
+      _cpp_size -= info._size;
 
       // We have to protect modifications to the table from recursive
       // calls by turning off _track_memory_usage while we adjust it.
@@ -584,26 +645,39 @@ ns_remove_void_pointer(void *ptr) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: MemoryUsage::ns_get_allocated_size
+//     Function: MemoryUsage::ns_get_current_cpp_size
 //       Access: Private
 //  Description: Returns the total number of bytes of allocated memory
-//               as counted, excluding the memory previously frozen.
+//               via the C++ operators new and delete as counted,
+//               not including the memory previously frozen.
 ////////////////////////////////////////////////////////////////////
 size_t MemoryUsage::
-ns_get_allocated_size() {
-  nassertr(_track_memory_usage, 0);
-  return _allocated_size;
+ns_get_current_cpp_size() {
+  return _current_cpp_size;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: MemoryUsage::ns_get_total_size
+//     Function: MemoryUsage::ns_get_cpp_size
 //       Access: Private
 //  Description: Returns the total number of bytes of allocated memory
-//               as counted, including the memory previously frozen.
+//               via the C++ operators new and delete as counted,
+//               including the memory previously frozen.
+////////////////////////////////////////////////////////////////////
+size_t MemoryUsage::
+ns_get_cpp_size() {
+  return _cpp_size;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryUsage::ns_get_total_size
+//       Access: Private
+//  Description: Returns the total size of the dynamic heap, as nearly
+//               as can be determined, including all allocated memory
+//               if possible, in addition to that tracked by
+//               get_cpp_size().
 ////////////////////////////////////////////////////////////////////
 size_t MemoryUsage::
 ns_get_total_size() {
-  nassertr(_track_memory_usage, 0);
   return _total_size;
 }
 
@@ -753,7 +827,7 @@ ns_get_pointers_with_zero_count(MemoryUsagePointers &result) {
 void MemoryUsage::
 ns_freeze() {
   _count = 0;
-  _allocated_size = 0;
+  _current_cpp_size = 0;
   _trend_types.clear();
   _trend_ages.clear();
   _freeze_index++;
@@ -884,7 +958,7 @@ consolidate_void_ptr(MemoryInfo &info) {
     info._size = typed_info.get_size();
     info._flags |= MemoryInfo::F_size_known;
     if (typed_info._freeze_index == _freeze_index) {
-      _allocated_size += info._size;
+      _current_cpp_size += info._size;
     }
   }
 
@@ -896,7 +970,7 @@ consolidate_void_ptr(MemoryInfo &info) {
   // entry.
   if (info._freeze_index == _freeze_index) {
     _count--;
-    _allocated_size -= info._size;
+    _current_cpp_size -= info._size;
   }
     
   // We have to protect modifications to the table from recursive

+ 27 - 5
panda/src/express/memoryUsage.h

@@ -67,17 +67,33 @@ public:
 #ifdef NDEBUG
 public:
   INLINE static bool is_tracking() { return false; }
-  INLINE static size_t get_allocated_size() { return 0; }
+  INLINE static bool is_counting() { return false; }
+  INLINE static size_t get_current_cpp_size() { return 0; }
+  INLINE static bool has_cpp_size() { return false; }
+  INLINE static size_t get_cpp_size() { return 0; }
+  INLINE static bool has_total_size() { return false; }
+  INLINE static size_t get_total_size() { return 0; }
 
 #else  // NDEBUG
 public:
   static void *operator_new_handler(size_t size);
   static void operator_delete_handler(void *ptr);
 
+#if defined(WIN32_VC) && defined(_DEBUG)
+  static int win32_malloc_hook(int alloc_type, void *ptr, 
+                               size_t size, int block_use, long request, 
+                               const unsigned char *filename, int line);
+#endif
+    
 PUBLISHED:
   INLINE static bool is_tracking();
-  INLINE static size_t get_allocated_size();
+  INLINE static bool is_counting();
+  INLINE static size_t get_current_cpp_size();
+  INLINE static bool has_cpp_size();
+  INLINE static size_t get_cpp_size();
+  INLINE static bool has_total_size();
   INLINE static size_t get_total_size();
+
   INLINE static int get_num_pointers();
   INLINE static void get_pointers(MemoryUsagePointers &result);
   INLINE static void get_pointers_of_type(MemoryUsagePointers &result,
@@ -105,7 +121,8 @@ private:
   void ns_record_void_pointer(void *ptr, size_t size);
   void ns_remove_void_pointer(void *ptr);
 
-  size_t ns_get_allocated_size();
+  size_t ns_get_current_cpp_size();
+  size_t ns_get_cpp_size();
   size_t ns_get_total_size();
   int ns_get_num_pointers();
   void ns_get_pointers(MemoryUsagePointers &result);
@@ -125,12 +142,16 @@ private:
 
   static MemoryUsage *_global_ptr;
 
-  // Cannot use a pmap, since that would be recursive!
+  // We shouldn't use a pmap, since that would be recursive!
+  // Actually, it turns out that it doesn't matter, since somehow the
+  // pallocator gets used even though we specify dallocator here, so
+  // we have to make special code that handles the recursion anyway.
   typedef map<void *, MemoryInfo, less<void *>, dallocator<MemoryInfo> > Table;
   Table _table;
   int _freeze_index;
   int _count;
-  size_t _allocated_size;
+  size_t _current_cpp_size;
+  size_t _cpp_size;
   size_t _total_size;
 
   class TypeHistogram {
@@ -165,6 +186,7 @@ private:
 
 
   bool _track_memory_usage;
+  bool _count_memory_usage;
 
 #endif  // NDEBUG
 };

+ 6 - 0
panda/src/express/memoryUsagePointerCounts.cxx

@@ -20,6 +20,9 @@
 #include "memoryUsagePointerCounts.h"
 #include "memoryInfo.h"
 
+#ifndef NDEBUG
+// Nothing in this module gets compiled in NDEBUG mode.
+
 ////////////////////////////////////////////////////////////////////
 //     Function: MemoryUsagePointerCounts::add_info
 //       Access: Public
@@ -75,3 +78,6 @@ output_bytes(ostream &out, size_t size) {
     out << size / (1024 * 1024) << " Mb";
   }
 }
+
+#endif  // NDEBUG
+

+ 7 - 3
panda/src/pstatclient/pStatClient.cxx

@@ -40,7 +40,8 @@
 PStatClient *PStatClient::_global_pstats = NULL;
 
 #ifndef CPPPARSER
-PStatCollector _memory_usage_pcollector("Panda memory usage");
+PStatCollector _memory_usage_pcollector("Memory usage");
+PStatCollector _cpp_usage_pcollector("Memory usage:C++");
 #endif
 
 ////////////////////////////////////////////////////////////////////
@@ -371,10 +372,13 @@ main_tick() {
   // code inside the MemoryUsage class, where it fits a little better,
   // simply because MemoryUsage is a very low-level class that doesn't
   // know about PStatClient.
-  if (MemoryUsage::is_tracking()) {
+  if (MemoryUsage::has_cpp_size()) {
+    _cpp_usage_pcollector.set_level(MemoryUsage::get_cpp_size());
+  }
+  if (MemoryUsage::has_total_size()) {
     _memory_usage_pcollector.set_level(MemoryUsage::get_total_size());
   }
-  
+
   get_global_pstats()->get_main_thread().new_frame();
 }
 

+ 4 - 3
panda/src/pstatclient/pStatProperties.cxx

@@ -145,9 +145,10 @@ static LevelCollectorProperties level_properties[] = {
   { 1, "Nodes",                            { 0.4, 0.2, 0.8 },  "", 500.0 },
   { 1, "Nodes:GeomNodes",                  { 0.8, 0.2, 0.0 } },
   { 1, "State changes",                    { 1.0, 0.5, 0.2 },  "", 500.0 },
-  { 1, "State changes:Transforms",         { 0.2, 0.2, 0.8 }, },
-  { 1, "State changes:Textures",           { 0.8, 0.2, 0.2 }, },
-  { 1, "Panda memory usage",               { 0.8, 0.2, 0.5 },  "MB", 64, 1048576 },
+  { 1, "State changes:Transforms",         { 0.2, 0.2, 0.8 } },
+  { 1, "State changes:Textures",           { 0.8, 0.2, 0.2 } },
+  { 1, "Memory usage",                     { 0.8, 0.2, 0.5 },  "MB", 64, 1048576 },
+  { 1, "Memory usage:C++",                 { 0.2, 0.2, 1.0 } },
   { 0, NULL }
 };