From 21c4a03c16c72e05f963ff84ba9e1a40dda8ce65 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 8 Jun 2001 00:00:44 +0000 Subject: [PATCH] track python memory --- panda/src/express/memoryUsage.I | 38 ++++++ panda/src/express/memoryUsage.cxx | 158 ++++++++++++++++------ panda/src/express/memoryUsage.h | 6 + panda/src/graph/namedNode.cxx | 9 ++ panda/src/graph/namedNode.h | 1 + panda/src/pstatclient/pStatClient.cxx | 16 ++- panda/src/pstatclient/pStatProperties.cxx | 3 +- 7 files changed, 181 insertions(+), 50 deletions(-) diff --git a/panda/src/express/memoryUsage.I b/panda/src/express/memoryUsage.I index b76169be9f..0641281e95 100644 --- a/panda/src/express/memoryUsage.I +++ b/panda/src/express/memoryUsage.I @@ -161,7 +161,14 @@ get_current_cpp_size() { //////////////////////////////////////////////////////////////////// INLINE bool MemoryUsage:: has_cpp_size() { +#if defined(WIN32_VC) && defined(_DEBUG) + // Windows in debug mode can count C++ size without having to do a + // full track. + return is_counting(); +#else + // Other systems require the full hammer. return is_tracking(); +#endif } //////////////////////////////////////////////////////////////////// @@ -176,6 +183,37 @@ get_cpp_size() { return get_global_ptr()->ns_get_cpp_size(); } +//////////////////////////////////////////////////////////////////// +// Function: MemoryUsage::has_interpreter_size +// Access: Public, Static +// Description: Returns true if the value returned by +// get_interpreter_size() is meaningful on this particular +// system with this particular configuration, false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool MemoryUsage:: +has_interpreter_size() { +#ifdef TRACK_IN_INTERPRETER + return is_counting(); +#else + return false; +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: MemoryUsage::get_interpreter_size +// Access: Public, Static +// Description: Returns the total number of bytes of allocated memory +// while the high-level languange code is running. This +// number is only meaningful if both Panda and the +// high-level language are single-threaded, and running +// in the same thread. +//////////////////////////////////////////////////////////////////// +INLINE size_t MemoryUsage:: +get_interpreter_size() { + return get_global_ptr()->ns_get_interpreter_size(); +} + //////////////////////////////////////////////////////////////////// // Function: MemoryUsage::has_total_size // Access: Public, Static diff --git a/panda/src/express/memoryUsage.cxx b/panda/src/express/memoryUsage.cxx index e417d3faed..4e717f820e 100644 --- a/panda/src/express/memoryUsage.cxx +++ b/panda/src/express/memoryUsage.cxx @@ -29,6 +29,8 @@ #endif #include "memoryUsage.h" +#include "interrogate_request.h" + #if defined(WIN32_VC) && defined(_DEBUG) #include #endif @@ -41,6 +43,14 @@ #include #endif +// This flag is set true in is_counting() mode to indicate that the +// malloc operation is coming from C++ operator new or delete. +static bool _is_cpp_operator = false; + +// This flag is used to protect the operator new/delete handlers +// against recursive entry. +static bool _recursion_protect = false; + MemoryUsage *MemoryUsage::_global_ptr = (MemoryUsage *)NULL; // The cutoff ages, in seconds, for the various buckets in the AgeHistogram. @@ -256,8 +266,24 @@ remove_pointer(ReferenceCount *ptr) { //////////////////////////////////////////////////////////////////// void *MemoryUsage:: operator_new_handler(size_t size) { - void *ptr = default_operator_new(size); - get_global_ptr()->ns_record_void_pointer(ptr, size); + void *ptr; + + if (_recursion_protect) { + ptr = default_operator_new(size); + + } else { + MemoryUsage *mu = get_global_ptr(); + if (mu->_track_memory_usage) { + ptr = default_operator_new(size); + get_global_ptr()->ns_record_void_pointer(ptr, size); + + } else { + _is_cpp_operator = true; + ptr = default_operator_new(size); + _is_cpp_operator = false; + } + } + return ptr; } @@ -272,8 +298,20 @@ operator_new_handler(size_t size) { //////////////////////////////////////////////////////////////////// void MemoryUsage:: operator_delete_handler(void *ptr) { - get_global_ptr()->ns_remove_void_pointer(ptr); - default_operator_delete(ptr); + if (_recursion_protect) { + default_operator_delete(ptr); + + } else { + MemoryUsage *mu = get_global_ptr(); + if (mu->_track_memory_usage) { + mu->ns_remove_void_pointer(ptr); + default_operator_delete(ptr); + } else { + _is_cpp_operator = true; + default_operator_delete(ptr); + _is_cpp_operator = false; + } + } } #if defined(WIN32_VC) && defined(_DEBUG) @@ -289,20 +327,38 @@ 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; + if (!_recursion_protect) { + MemoryUsage *mu = get_global_ptr(); + if (mu->_count_memory_usage) { + int increment = 0; + switch (alloc_type) { + case _HOOK_ALLOC: + increment = size; + break; + + case _HOOK_REALLOC: + increment = size - _msize(ptr); + break; + + case _HOOK_FREE: + increment = -_msize(ptr); + break; + } - case _HOOK_REALLOC: - mu->_total_size += size - _msize(ptr); - break; - - case _HOOK_FREE: - mu->_total_size -= _msize(ptr); - break; + mu->_total_size += increment; + + /* + This isn't working reliably right now. + if (_is_cpp_operator) { + mu->_cpp_size += increment; + } + */ + +#ifdef TRACK_IN_INTERPRETER + if (in_interpreter) { + mu->_interpreter_size += increment; + } +#endif } } @@ -350,6 +406,8 @@ MemoryUsage() { #if defined(WIN32_VC) && defined(_DEBUG) if (_count_memory_usage) { + global_operator_new = &operator_new_handler; + global_operator_delete = &operator_delete_handler; _CrtSetAllocHook(&win32_malloc_hook); } #endif @@ -358,6 +416,7 @@ MemoryUsage() { _count = 0; _current_cpp_size = 0; _cpp_size = 0; + _interpreter_size = 0; _total_size = 0; } @@ -386,11 +445,11 @@ void MemoryUsage:: ns_record_pointer(ReferenceCount *ptr) { if (_track_memory_usage) { // We have to protect modifications to the table from recursive - // calls by turning off _track_memory_usage while we adjust it. - _track_memory_usage = false; + // calls by toggling _recursion_protect while we adjust it. + _recursion_protect = true; pair insert_result = _table.insert(Table::value_type((void *)ptr, MemoryInfo())); - _track_memory_usage = true; + _recursion_protect = false; // This shouldn't fail. assert(insert_result.first != _table.end()); @@ -516,11 +575,11 @@ ns_remove_pointer(ReferenceCount *ptr) { double now = TrueClock::get_ptr()->get_real_time(); // We have to protect modifications to the table from recursive - // calls by turning off _track_memory_usage while we adjust it. - _track_memory_usage = false; + // calls by toggling _recursion_protect while we adjust it. + _recursion_protect = true; _trend_types.add_info(info.get_type(), info); _trend_ages.add_info(now - info._time, info); - _track_memory_usage = true; + _recursion_protect = false; } if ((info._flags & (MemoryInfo::F_got_ref | MemoryInfo::F_got_void)) == 0) { @@ -533,10 +592,10 @@ ns_remove_pointer(ReferenceCount *ptr) { _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. - _track_memory_usage = false; + // calls by toggling _recursion_protect while we adjust it. + _recursion_protect = true; _table.erase(ti); - _track_memory_usage = true; + _recursion_protect = false; } } } @@ -552,13 +611,12 @@ void MemoryUsage:: ns_record_void_pointer(void *ptr, size_t size) { if (_track_memory_usage) { // We have to protect modifications to the table from recursive - // calls by turning off _track_memory_usage while we adjust it. - _track_memory_usage = false; + // calls by toggling _recursion_protect while we adjust it. + _recursion_protect = true; pair insert_result = _table.insert(Table::value_type((void *)ptr, MemoryInfo())); - _track_memory_usage = true; - - // This shouldn't fail. + _recursion_protect = false; + assert(insert_result.first != _table.end()); if (insert_result.second) { @@ -636,10 +694,10 @@ ns_remove_void_pointer(void *ptr) { _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. - _track_memory_usage = false; + // calls by toggling _recursion_protect while we adjust it. + _recursion_protect = true; _table.erase(ti); - _track_memory_usage = true; + _recursion_protect = false; } } } @@ -668,6 +726,20 @@ ns_get_cpp_size() { return _cpp_size; } +//////////////////////////////////////////////////////////////////// +// Function: MemoryUsage::ns_get_interpreter_size +// Access: Private +// Description: Returns the total number of bytes of allocated memory +// while the high-level languange code is running. This +// number is only meaningful if both Panda and the +// high-level language are single-threaded, and running +// in the same thread. +//////////////////////////////////////////////////////////////////// +size_t MemoryUsage:: +ns_get_interpreter_size() { + return _interpreter_size; +} + //////////////////////////////////////////////////////////////////// // Function: MemoryUsage::ns_get_total_size // Access: Private @@ -843,8 +915,8 @@ void MemoryUsage:: ns_show_current_types() { nassertv(_track_memory_usage); // We have to protect modifications to the table from recursive - // calls by turning off _track_memory_usage while we adjust it. - _track_memory_usage = false; + // calls by toggling _recursion_protect while we adjust it. + _recursion_protect = true; TypeHistogram hist; @@ -857,7 +929,7 @@ ns_show_current_types() { } hist.show(); - _track_memory_usage = true; + _recursion_protect = false; } //////////////////////////////////////////////////////////////////// @@ -883,8 +955,8 @@ ns_show_current_ages() { nassertv(_track_memory_usage); // We have to protect modifications to the table from recursive - // calls by turning off _track_memory_usage while we adjust it. - _track_memory_usage = false; + // calls by toggling _recursion_protect while we adjust it. + _recursion_protect = true; AgeHistogram hist; double now = TrueClock::get_ptr()->get_real_time(); @@ -899,7 +971,7 @@ ns_show_current_ages() { hist.show(); - _track_memory_usage = true; + _recursion_protect = false; } //////////////////////////////////////////////////////////////////// @@ -974,10 +1046,10 @@ consolidate_void_ptr(MemoryInfo &info) { } // We have to protect modifications to the table from recursive - // calls by turning off _track_memory_usage while we adjust it. - _track_memory_usage = false; + // calls by toggling _recursion_protect while we adjust it. + _recursion_protect = true; _table.erase(ti); - _track_memory_usage = true; + _recursion_protect = false; } diff --git a/panda/src/express/memoryUsage.h b/panda/src/express/memoryUsage.h index 2f03e1ad2d..fac58925a5 100644 --- a/panda/src/express/memoryUsage.h +++ b/panda/src/express/memoryUsage.h @@ -71,6 +71,8 @@ public: 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_interpreter_size() { return false; } + INLINE static size_t get_interpreter_size() { return 0; } INLINE static bool has_total_size() { return false; } INLINE static size_t get_total_size() { return 0; } @@ -91,6 +93,8 @@ PUBLISHED: 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_interpreter_size(); + INLINE static size_t get_interpreter_size(); INLINE static bool has_total_size(); INLINE static size_t get_total_size(); @@ -123,6 +127,7 @@ private: size_t ns_get_current_cpp_size(); size_t ns_get_cpp_size(); + size_t ns_get_interpreter_size(); size_t ns_get_total_size(); int ns_get_num_pointers(); void ns_get_pointers(MemoryUsagePointers &result); @@ -152,6 +157,7 @@ private: int _count; size_t _current_cpp_size; size_t _cpp_size; + size_t _interpreter_size; size_t _total_size; class TypeHistogram { diff --git a/panda/src/graph/namedNode.cxx b/panda/src/graph/namedNode.cxx index 1b7d4d408d..f8abf870ae 100644 --- a/panda/src/graph/namedNode.cxx +++ b/panda/src/graph/namedNode.cxx @@ -24,6 +24,15 @@ TypeHandle NamedNode::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: NamedNode::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +NamedNode:: +~NamedNode() { +} + //////////////////////////////////////////////////////////////////// // Function: NamedNode::make_copy // Access: Public, Virtual diff --git a/panda/src/graph/namedNode.h b/panda/src/graph/namedNode.h index afa802de30..8f90a4e79f 100644 --- a/panda/src/graph/namedNode.h +++ b/panda/src/graph/namedNode.h @@ -36,6 +36,7 @@ PUBLISHED: public: INLINE_GRAPH NamedNode(const NamedNode ©); INLINE_GRAPH void operator = (const NamedNode ©); + virtual ~NamedNode(); virtual Node *make_copy() const; virtual void output(ostream &out) const; diff --git a/panda/src/pstatclient/pStatClient.cxx b/panda/src/pstatclient/pStatClient.cxx index 9e56b532dd..bbfe656d68 100644 --- a/panda/src/pstatclient/pStatClient.cxx +++ b/panda/src/pstatclient/pStatClient.cxx @@ -40,8 +40,9 @@ PStatClient *PStatClient::_global_pstats = NULL; #ifndef CPPPARSER -PStatCollector _memory_usage_pcollector("Memory usage"); -PStatCollector _cpp_usage_pcollector("Memory usage:C++"); +PStatCollector _total_size_pcollector("Memory usage"); +PStatCollector _cpp_size_pcollector("Memory usage:C++"); +PStatCollector _interpreter_size_pcollector("Memory usage:Interpreter"); #endif //////////////////////////////////////////////////////////////////// @@ -372,11 +373,14 @@ 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::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()); + _total_size_pcollector.set_level(MemoryUsage::get_total_size()); + } + if (MemoryUsage::has_cpp_size()) { + _cpp_size_pcollector.set_level(MemoryUsage::get_cpp_size()); + } + if (MemoryUsage::has_interpreter_size()) { + _interpreter_size_pcollector.set_level(MemoryUsage::get_interpreter_size()); } get_global_pstats()->get_main_thread().new_frame(); diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index 3f2eb4aa8f..e255fd9071 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -147,8 +147,9 @@ static LevelCollectorProperties level_properties[] = { { 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, "Memory usage", { 0.8, 0.2, 0.5 }, "MB", 64, 1048576 }, + { 1, "Memory usage", { 0.5, 1.0, 0.5 }, "MB", 64, 1048576 }, { 1, "Memory usage:C++", { 0.2, 0.2, 1.0 } }, + { 1, "Memory usage:Interpreter", { 0.8, 0.2, 0.5 } }, { 0, NULL } };