track python memory

This commit is contained in:
David Rose 2001-06-08 00:00:44 +00:00
parent e01f50844f
commit 21c4a03c16
7 changed files with 181 additions and 50 deletions

View File

@ -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

View File

@ -29,6 +29,8 @@
#endif
#include "memoryUsage.h"
#include "interrogate_request.h"
#if defined(WIN32_VC) && defined(_DEBUG)
#include <crtdbg.h>
#endif
@ -41,6 +43,14 @@
#include <algorithm>
#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<Table::iterator, bool> 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<Table::iterator, bool> 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;
}

View File

@ -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 {

View File

@ -24,6 +24,15 @@
TypeHandle NamedNode::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: NamedNode::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
NamedNode::
~NamedNode() {
}
////////////////////////////////////////////////////////////////////
// Function: NamedNode::make_copy
// Access: Public, Virtual

View File

@ -36,6 +36,7 @@ PUBLISHED:
public:
INLINE_GRAPH NamedNode(const NamedNode &copy);
INLINE_GRAPH void operator = (const NamedNode &copy);
virtual ~NamedNode();
virtual Node *make_copy() const;
virtual void output(ostream &out) const;

View File

@ -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();

View File

@ -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 }
};