mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
max-heap-size
This commit is contained in:
parent
c9201caa41
commit
c11e8411d9
@ -135,6 +135,7 @@ MemoryHook() {
|
|||||||
_total_heap_array_size = 0;
|
_total_heap_array_size = 0;
|
||||||
_requested_heap_size = 0;
|
_requested_heap_size = 0;
|
||||||
_total_mmap_size = 0;
|
_total_mmap_size = 0;
|
||||||
|
_max_heap_size = ~(size_t)0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +153,7 @@ MemoryHook(const MemoryHook ©) :
|
|||||||
_total_heap_array_size = copy._total_heap_array_size;
|
_total_heap_array_size = copy._total_heap_array_size;
|
||||||
_requested_heap_size = copy._requested_heap_size;
|
_requested_heap_size = copy._requested_heap_size;
|
||||||
_total_mmap_size = copy._total_mmap_size;
|
_total_mmap_size = copy._total_mmap_size;
|
||||||
|
_max_heap_size = copy._max_heap_size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
((MutexImpl &)copy._lock).lock();
|
((MutexImpl &)copy._lock).lock();
|
||||||
@ -183,12 +185,6 @@ MemoryHook::
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void *MemoryHook::
|
void *MemoryHook::
|
||||||
heap_alloc_single(size_t size) {
|
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
|
#ifdef MEMORY_HOOK_MALLOC_LOCK
|
||||||
_lock.lock();
|
_lock.lock();
|
||||||
void *alloc = call_malloc(inflate_size(size));
|
void *alloc = call_malloc(inflate_size(size));
|
||||||
@ -202,6 +198,17 @@ heap_alloc_single(size_t size) {
|
|||||||
abort();
|
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);
|
return alloc_to_ptr(alloc, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,12 +251,6 @@ heap_free_single(void *ptr) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void *MemoryHook::
|
void *MemoryHook::
|
||||||
heap_alloc_array(size_t size) {
|
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
|
#ifdef MEMORY_HOOK_MALLOC_LOCK
|
||||||
_lock.lock();
|
_lock.lock();
|
||||||
void *alloc = call_malloc(inflate_size(size));
|
void *alloc = call_malloc(inflate_size(size));
|
||||||
@ -263,6 +264,17 @@ heap_alloc_array(size_t size) {
|
|||||||
abort();
|
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);
|
return alloc_to_ptr(alloc, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,3 +502,21 @@ get_deleted_chain(size_t buffer_size) {
|
|||||||
_lock.release();
|
_lock.release();
|
||||||
return chain;
|
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 _total_heap_array_size;
|
||||||
TVOLATILE PN_int32 _requested_heap_size;
|
TVOLATILE PN_int32 _requested_heap_size;
|
||||||
TVOLATILE PN_int32 _total_mmap_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:
|
private:
|
||||||
size_t _page_size;
|
size_t _page_size;
|
||||||
|
@ -137,7 +137,7 @@ get_total_cpp_size() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE size_t MemoryUsage::
|
INLINE size_t MemoryUsage::
|
||||||
get_panda_heap_single_size() {
|
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::
|
INLINE size_t MemoryUsage::
|
||||||
get_panda_heap_array_size() {
|
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() {
|
get_panda_heap_overhead() {
|
||||||
#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||||
MemoryUsage *mu = get_global_ptr();
|
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
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
@ -177,7 +177,7 @@ get_panda_heap_overhead() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE size_t MemoryUsage::
|
INLINE size_t MemoryUsage::
|
||||||
get_panda_mmap_size() {
|
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)
|
#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||||
return mu->_requested_heap_size;
|
return mu->_requested_heap_size;
|
||||||
#else
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,8 +382,34 @@ MemoryUsage(const MemoryHook ©) : MemoryHook(copy) {
|
|||||||
PRC_DESC("Set this to true to enable full-force tracking of C++ allocations "
|
PRC_DESC("Set this to true to enable full-force tracking of C++ allocations "
|
||||||
"and recordkeeping by type. It's quite expensive."));
|
"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;
|
_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
|
#ifdef USE_MEMORY_NOWRAPPERS
|
||||||
#error Cannot compile MemoryUsage without malloc wrappers!
|
#error Cannot compile MemoryUsage without malloc wrappers!
|
||||||
#endif
|
#endif
|
||||||
@ -405,6 +431,37 @@ MemoryUsage(const MemoryHook ©) : MemoryHook(copy) {
|
|||||||
_total_size = 0;
|
_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
|
// Function: MemoryUsage::get_global_ptr
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
@ -464,6 +521,16 @@ ns_record_pointer(ReferenceCount *ptr) {
|
|||||||
// that we also protect ourselves against a possible recursive
|
// that we also protect ourselves against a possible recursive
|
||||||
// call in TrueClock::get_global_ptr().
|
// call in TrueClock::get_global_ptr().
|
||||||
_recursion_protect = false;
|
_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;
|
Table::iterator ti;
|
||||||
ti = _table.find(ptr);
|
ti = _table.find(ptr);
|
||||||
if (ti == _table.end()) {
|
if (ti == _table.end()) {
|
||||||
express_cat.error()
|
if (_startup_track_memory_usage) {
|
||||||
<< "Attempt to update type to " << type << " for unrecorded pointer "
|
express_cat.error()
|
||||||
<< (void *)ptr << "!\n";
|
<< "Attempt to update type to " << type << " for unrecorded pointer "
|
||||||
nassertv(false);
|
<< (void *)ptr << "!\n";
|
||||||
|
nassertv(false);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,10 +583,12 @@ ns_update_type(ReferenceCount *ptr, TypedObject *typed_ptr) {
|
|||||||
Table::iterator ti;
|
Table::iterator ti;
|
||||||
ti = _table.find(ptr);
|
ti = _table.find(ptr);
|
||||||
if (ti == _table.end()) {
|
if (ti == _table.end()) {
|
||||||
express_cat.error()
|
if (_startup_track_memory_usage) {
|
||||||
<< "Attempt to update type to " << typed_ptr->get_type()
|
express_cat.error()
|
||||||
<< " for unrecorded pointer "
|
<< "Attempt to update type to " << typed_ptr->get_type()
|
||||||
<< (void *)ptr << "!\n";
|
<< " for unrecorded pointer "
|
||||||
|
<< (void *)ptr << "!\n";
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,11 +612,13 @@ ns_remove_pointer(ReferenceCount *ptr) {
|
|||||||
Table::iterator ti;
|
Table::iterator ti;
|
||||||
ti = _table.find(ptr);
|
ti = _table.find(ptr);
|
||||||
if (ti == _table.end()) {
|
if (ti == _table.end()) {
|
||||||
express_cat.error()
|
if (_startup_track_memory_usage) {
|
||||||
<< "Attempt to remove pointer " << (void *)ptr
|
express_cat.error()
|
||||||
<< ", not in table.\n"
|
<< "Attempt to remove pointer " << (void *)ptr
|
||||||
<< "Possibly a double-destruction.\n";
|
<< ", not in table.\n"
|
||||||
nassertv(false);
|
<< "Possibly a double-destruction.\n";
|
||||||
|
nassertv(false);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +91,9 @@ PUBLISHED:
|
|||||||
INLINE static void show_current_ages();
|
INLINE static void show_current_ages();
|
||||||
INLINE static void show_trend_ages();
|
INLINE static void show_trend_ages();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void overflow_heap_size();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryUsage(const MemoryHook ©);
|
MemoryUsage(const MemoryHook ©);
|
||||||
static MemoryUsage *get_global_ptr();
|
static MemoryUsage *get_global_ptr();
|
||||||
@ -183,7 +186,11 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
bool _track_memory_usage;
|
bool _track_memory_usage;
|
||||||
|
bool _startup_track_memory_usage;
|
||||||
bool _count_memory_usage;
|
bool _count_memory_usage;
|
||||||
|
bool _report_memory_usage;
|
||||||
|
double _report_memory_interval;
|
||||||
|
double _last_report_time;
|
||||||
|
|
||||||
static bool _recursion_protect;
|
static bool _recursion_protect;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user