mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
max-heap-size
This commit is contained in:
parent
c9201caa41
commit
c11e8411d9
@ -135,6 +135,7 @@ MemoryHook() {
|
||||
_total_heap_array_size = 0;
|
||||
_requested_heap_size = 0;
|
||||
_total_mmap_size = 0;
|
||||
_max_heap_size = ~(size_t)0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -152,6 +153,7 @@ MemoryHook(const MemoryHook ©) :
|
||||
_total_heap_array_size = copy._total_heap_array_size;
|
||||
_requested_heap_size = copy._requested_heap_size;
|
||||
_total_mmap_size = copy._total_mmap_size;
|
||||
_max_heap_size = copy._max_heap_size;
|
||||
#endif
|
||||
|
||||
((MutexImpl &)copy._lock).lock();
|
||||
@ -183,12 +185,6 @@ MemoryHook::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void *MemoryHook::
|
||||
heap_alloc_single(size_t size) {
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
// In the DO_MEMORY_USAGE case, we want to track the total size of
|
||||
// allocated bytes on the heap.
|
||||
AtomicAdjust::add(_total_heap_single_size, (PN_int32)size);
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
#ifdef MEMORY_HOOK_MALLOC_LOCK
|
||||
_lock.lock();
|
||||
void *alloc = call_malloc(inflate_size(size));
|
||||
@ -202,6 +198,17 @@ heap_alloc_single(size_t size) {
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
// In the DO_MEMORY_USAGE case, we want to track the total size of
|
||||
// allocated bytes on the heap.
|
||||
AtomicAdjust::add(_total_heap_single_size, (PN_int32)size);
|
||||
if ((size_t)AtomicAdjust::get(_total_heap_single_size) +
|
||||
(size_t)AtomicAdjust::get(_total_heap_array_size) >
|
||||
_max_heap_size) {
|
||||
overflow_heap_size();
|
||||
}
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
return alloc_to_ptr(alloc, size);
|
||||
}
|
||||
|
||||
@ -244,12 +251,6 @@ heap_free_single(void *ptr) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void *MemoryHook::
|
||||
heap_alloc_array(size_t size) {
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
// In the DO_MEMORY_USAGE case, we want to track the total size of
|
||||
// allocated bytes on the heap.
|
||||
AtomicAdjust::add(_total_heap_array_size, (PN_int32)size);
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
#ifdef MEMORY_HOOK_MALLOC_LOCK
|
||||
_lock.lock();
|
||||
void *alloc = call_malloc(inflate_size(size));
|
||||
@ -263,6 +264,17 @@ heap_alloc_array(size_t size) {
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
// In the DO_MEMORY_USAGE case, we want to track the total size of
|
||||
// allocated bytes on the heap.
|
||||
AtomicAdjust::add(_total_heap_array_size, (PN_int32)size);
|
||||
if ((size_t)AtomicAdjust::get(_total_heap_single_size) +
|
||||
(size_t)AtomicAdjust::get(_total_heap_array_size) >
|
||||
_max_heap_size) {
|
||||
overflow_heap_size();
|
||||
}
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
return alloc_to_ptr(alloc, size);
|
||||
}
|
||||
|
||||
@ -490,3 +502,21 @@ get_deleted_chain(size_t buffer_size) {
|
||||
_lock.release();
|
||||
return chain;
|
||||
}
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryHook::overflow_heap_size
|
||||
// Access: Protected, Virtual
|
||||
// Description: This callback method is called whenever the total
|
||||
// allocated heap size exceeds _max_heap_size. It's
|
||||
// mainly intended for reporting memory leaks, on the
|
||||
// assumption that once we cross some specified
|
||||
// threshold, we're just leaking memory.
|
||||
//
|
||||
// The implementation for this method is in MemoryUsage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryHook::
|
||||
overflow_heap_size() {
|
||||
_max_heap_size = ~(size_t)0;
|
||||
}
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
@ -82,7 +82,13 @@ protected:
|
||||
TVOLATILE PN_int32 _total_heap_array_size;
|
||||
TVOLATILE PN_int32 _requested_heap_size;
|
||||
TVOLATILE PN_int32 _total_mmap_size;
|
||||
#endif
|
||||
|
||||
// If the allocated heap size crosses this threshold, we call
|
||||
// overflow_heap_size().
|
||||
size_t _max_heap_size;
|
||||
|
||||
virtual void overflow_heap_size();
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
private:
|
||||
size_t _page_size;
|
||||
|
@ -137,7 +137,7 @@ get_total_cpp_size() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t MemoryUsage::
|
||||
get_panda_heap_single_size() {
|
||||
return get_global_ptr()->_total_heap_single_size;
|
||||
return AtomicAdjust::get(get_global_ptr()->_total_heap_single_size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -148,7 +148,7 @@ get_panda_heap_single_size() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t MemoryUsage::
|
||||
get_panda_heap_array_size() {
|
||||
return get_global_ptr()->_total_heap_array_size;
|
||||
return AtomicAdjust::get(get_global_ptr()->_total_heap_array_size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -163,7 +163,7 @@ INLINE size_t MemoryUsage::
|
||||
get_panda_heap_overhead() {
|
||||
#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||
MemoryUsage *mu = get_global_ptr();
|
||||
return mu->_requested_heap_size - mu->_total_heap_single_size - mu->_total_heap_array_size;
|
||||
return AtomicAdjust::get(mu->_requested_heap_size) - AtomicAdjust::get(mu->_total_heap_single_size) - AtomicAdjust::get(mu->_total_heap_array_size);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
@ -177,7 +177,7 @@ get_panda_heap_overhead() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t MemoryUsage::
|
||||
get_panda_mmap_size() {
|
||||
return get_global_ptr()->_total_mmap_size;
|
||||
return AtomicAdjust::get(get_global_ptr()->_total_mmap_size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -246,7 +246,7 @@ get_total_size() {
|
||||
#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||
return mu->_requested_heap_size;
|
||||
#else
|
||||
return mu->_total_heap_single_size + mu->_total_heap_array_size;
|
||||
return AtomicAdjust::get(mu->_total_heap_single_size) + AtomicAdjust::get(mu->_total_heap_array_size);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -382,8 +382,34 @@ MemoryUsage(const MemoryHook ©) : MemoryHook(copy) {
|
||||
PRC_DESC("Set this to true to enable full-force tracking of C++ allocations "
|
||||
"and recordkeeping by type. It's quite expensive."));
|
||||
|
||||
// Since enabling this after startup might cause bogus errors, we'd
|
||||
// like to know if this happened, so we can squelch those error
|
||||
// messages.
|
||||
_startup_track_memory_usage = _track_memory_usage;
|
||||
|
||||
_report_memory_usage = ConfigVariableBool
|
||||
("report-memory-usage", false,
|
||||
PRC_DESC("Set this true to enable automatic reporting of allocated objects "
|
||||
"at the interval specified by report-memory-interval. This also "
|
||||
"requires track-memory-usage."));
|
||||
_report_memory_interval = ConfigVariableDouble
|
||||
("report-memory-interval", 5.0,
|
||||
PRC_DESC("This is the interval, in seconds, for reports of currently allocated "
|
||||
"memory, when report-memory-usage is true."));
|
||||
_last_report_time = 0.0;
|
||||
|
||||
_count_memory_usage = false;
|
||||
|
||||
int max_heap_size = ConfigVariableInt
|
||||
("max-heap-size", 0,
|
||||
PRC_DESC("If this is nonzero, it is the maximum number of bytes expected "
|
||||
"to be allocated on the heap before we enter report-memory-usage "
|
||||
"mode automatically. The assumption is that once this limit "
|
||||
"has been crossed, we must be leaking."));
|
||||
if (max_heap_size != 0) {
|
||||
_max_heap_size = (size_t)max_heap_size;
|
||||
}
|
||||
|
||||
#ifdef USE_MEMORY_NOWRAPPERS
|
||||
#error Cannot compile MemoryUsage without malloc wrappers!
|
||||
#endif
|
||||
@ -405,6 +431,37 @@ MemoryUsage(const MemoryHook ©) : MemoryHook(copy) {
|
||||
_total_size = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::overflow_heap_size
|
||||
// Access: Protected, Virtual
|
||||
// Description: This callback method is called whenever the total
|
||||
// allocated heap size exceeds _max_heap_size. It's
|
||||
// mainly intended for reporting memory leaks, on the
|
||||
// assumption that once we cross some specified
|
||||
// threshold, we're just leaking memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsage::
|
||||
overflow_heap_size() {
|
||||
MemoryHook::overflow_heap_size();
|
||||
|
||||
express_cat.error()
|
||||
<< "Total allocated memory has reached "
|
||||
<< get_panda_heap_single_size() + get_panda_heap_array_size()
|
||||
<< " bytes."
|
||||
<< "\n heap single: " << get_panda_heap_single_size()
|
||||
<< "\n heap array: " << get_panda_heap_array_size()
|
||||
<< "\n heap overhead: " << get_panda_heap_overhead()
|
||||
<< "\n mmap: " << get_panda_mmap_size()
|
||||
<< "\n interpreter: " << get_interpreter_size()
|
||||
<< "\n external: " << get_external_size()
|
||||
<< "\n total: " << get_total_size()
|
||||
<< "\n";
|
||||
|
||||
// Turn on spamful debugging.
|
||||
_track_memory_usage = true;
|
||||
_report_memory_usage = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::get_global_ptr
|
||||
// Access: Private, Static
|
||||
@ -464,6 +521,16 @@ ns_record_pointer(ReferenceCount *ptr) {
|
||||
// that we also protect ourselves against a possible recursive
|
||||
// call in TrueClock::get_global_ptr().
|
||||
_recursion_protect = false;
|
||||
|
||||
if (_report_memory_usage) {
|
||||
double now = TrueClock::get_global_ptr()->get_long_time();
|
||||
if (now - _last_report_time > _report_memory_interval) {
|
||||
_last_report_time = now;
|
||||
express_cat.info()
|
||||
<< "*** Current memory usage: " << get_total_size() << "\n";
|
||||
show_current_types();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -482,10 +549,12 @@ ns_update_type(ReferenceCount *ptr, TypeHandle type) {
|
||||
Table::iterator ti;
|
||||
ti = _table.find(ptr);
|
||||
if (ti == _table.end()) {
|
||||
express_cat.error()
|
||||
<< "Attempt to update type to " << type << " for unrecorded pointer "
|
||||
<< (void *)ptr << "!\n";
|
||||
nassertv(false);
|
||||
if (_startup_track_memory_usage) {
|
||||
express_cat.error()
|
||||
<< "Attempt to update type to " << type << " for unrecorded pointer "
|
||||
<< (void *)ptr << "!\n";
|
||||
nassertv(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -514,10 +583,12 @@ ns_update_type(ReferenceCount *ptr, TypedObject *typed_ptr) {
|
||||
Table::iterator ti;
|
||||
ti = _table.find(ptr);
|
||||
if (ti == _table.end()) {
|
||||
express_cat.error()
|
||||
<< "Attempt to update type to " << typed_ptr->get_type()
|
||||
<< " for unrecorded pointer "
|
||||
<< (void *)ptr << "!\n";
|
||||
if (_startup_track_memory_usage) {
|
||||
express_cat.error()
|
||||
<< "Attempt to update type to " << typed_ptr->get_type()
|
||||
<< " for unrecorded pointer "
|
||||
<< (void *)ptr << "!\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -541,11 +612,13 @@ ns_remove_pointer(ReferenceCount *ptr) {
|
||||
Table::iterator ti;
|
||||
ti = _table.find(ptr);
|
||||
if (ti == _table.end()) {
|
||||
express_cat.error()
|
||||
<< "Attempt to remove pointer " << (void *)ptr
|
||||
<< ", not in table.\n"
|
||||
<< "Possibly a double-destruction.\n";
|
||||
nassertv(false);
|
||||
if (_startup_track_memory_usage) {
|
||||
express_cat.error()
|
||||
<< "Attempt to remove pointer " << (void *)ptr
|
||||
<< ", not in table.\n"
|
||||
<< "Possibly a double-destruction.\n";
|
||||
nassertv(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -91,6 +91,9 @@ PUBLISHED:
|
||||
INLINE static void show_current_ages();
|
||||
INLINE static void show_trend_ages();
|
||||
|
||||
protected:
|
||||
virtual void overflow_heap_size();
|
||||
|
||||
private:
|
||||
MemoryUsage(const MemoryHook ©);
|
||||
static MemoryUsage *get_global_ptr();
|
||||
@ -183,7 +186,11 @@ private:
|
||||
|
||||
|
||||
bool _track_memory_usage;
|
||||
bool _startup_track_memory_usage;
|
||||
bool _count_memory_usage;
|
||||
bool _report_memory_usage;
|
||||
double _report_memory_interval;
|
||||
double _last_report_time;
|
||||
|
||||
static bool _recursion_protect;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user