Panda3D
memoryUsage.I
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file memoryUsage.I
10 * @author drose
11 * @date 2000-05-25
12 */
13
14/**
15 * Returns true if the user has Configured the variable 'track-memory-usage'
16 * to true, indicating that this class will be in effect. If this returns
17 * false, the user has indicated not to do any of this.
18 */
19ALWAYS_INLINE bool MemoryUsage::
21#ifdef DO_MEMORY_USAGE
22 return get_global_ptr()->_track_memory_usage;
23#else
24 return false;
25#endif
26}
27
28/**
29 * Indicates that the given pointer has been recently allocated.
30 */
31INLINE void MemoryUsage::
33#ifdef DO_MEMORY_USAGE
34 get_global_ptr()->ns_record_pointer(ptr);
35#endif
36}
37
38/**
39 * Indicates that the given pointer has been recently allocated.
40 */
41INLINE void MemoryUsage::
42record_pointer(void *ptr, TypeHandle type) {
43#ifdef DO_MEMORY_USAGE
44 get_global_ptr()->ns_record_pointer(ptr, type);
45#endif
46}
47
48/**
49 * Associates the indicated type with the given pointer. This should be
50 * called by functions (e.g. the constructor) that know more specifically
51 * what type of thing we've got; otherwise, the MemoryUsage database will know
52 * only that it's a "ReferenceCount".
53 */
54INLINE void MemoryUsage::
56#ifdef DO_MEMORY_USAGE
57 get_global_ptr()->ns_update_type((void *)ptr, type);
58#endif
59}
60
61/**
62 * Associates the indicated type with the given pointer. This flavor of
63 * update_type() also passes in the pointer as a TypedObject, and useful for
64 * objects that are, in fact, TypedObjects. Once the MemoryUsage database has
65 * the pointer as a TypedObject it doesn't need any more help.
66 */
67INLINE void MemoryUsage::
68update_type(ReferenceCount *ptr, TypedObject *typed_ptr) {
69#ifdef DO_MEMORY_USAGE
70 get_global_ptr()->ns_update_type((void *)ptr, typed_ptr);
71#endif
72}
73
74/**
75 * Associates the indicated type with the given pointer. This should be
76 * called by functions (e.g. the constructor) that know more specifically
77 * what type of thing we've got.
78 */
79INLINE void MemoryUsage::
80update_type(void *ptr, TypeHandle type) {
81#ifdef DO_MEMORY_USAGE
82 get_global_ptr()->ns_update_type(ptr, type);
83#endif
84}
85
86/**
87 * Indicates that the given pointer has been recently freed.
88 */
89INLINE void MemoryUsage::
91#ifdef DO_MEMORY_USAGE
92 get_global_ptr()->ns_remove_pointer(ptr);
93#endif
94}
95
96/**
97 * Returns true if the MemoryUsage object is currently tracking memory (e.g.
98 * track-memory-usage is configured #t).
99 */
100INLINE bool MemoryUsage::
101is_tracking() {
102#ifdef DO_MEMORY_USAGE
103 return get_global_ptr()->_track_memory_usage;
104#else
105 return false;
106#endif
107}
108
109/**
110 * Returns true if the MemoryUsage object is currently at least counting
111 * memory (e.g. this is a Windows debug build), even if it's not fully
112 * tracking it.
113 */
114INLINE bool MemoryUsage::
115is_counting() {
116#ifdef DO_MEMORY_USAGE
117 return get_global_ptr()->_count_memory_usage;
118#else
119 return false;
120#endif
121}
122
123/**
124 * Returns the total number of bytes of allocated memory consumed by C++
125 * objects, not including the memory previously frozen.
126 */
127INLINE size_t MemoryUsage::
129#ifdef DO_MEMORY_USAGE
130 return get_global_ptr()->_current_cpp_size;
131#else
132 return 0;
133#endif
134}
135
136/**
137 * Returns the total number of bytes of allocated memory consumed by C++
138 * objects, including the memory previously frozen.
139 */
140INLINE size_t MemoryUsage::
142#ifdef DO_MEMORY_USAGE
143 return get_global_ptr()->_total_cpp_size;
144#else
145 return 0;
146#endif
147}
148
149/**
150 * Returns the total number of bytes allocated from the heap from code within
151 * Panda, for individual objects.
152 */
153INLINE size_t MemoryUsage::
155#ifdef DO_MEMORY_USAGE
156 return (size_t)AtomicAdjust::get(get_global_ptr()->_total_heap_single_size);
157#else
158 return 0;
159#endif
160}
161
162/**
163 * Returns the total number of bytes allocated from the heap from code within
164 * Panda, for arrays.
165 */
166INLINE size_t MemoryUsage::
168#ifdef DO_MEMORY_USAGE
169 return (size_t)AtomicAdjust::get(get_global_ptr()->_total_heap_array_size);
170#else
171 return 0;
172#endif
173}
174
175/**
176 * Returns the extra bytes allocated from the system that are not immediately
177 * used for holding allocated objects. This can only be determined if
178 * ALTERNATIVE_MALLOC is enabled.
179 */
180INLINE size_t MemoryUsage::
182#if defined(DO_MEMORY_USAGE) && (defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2))
183 MemoryUsage *mu = get_global_ptr();
184 return (size_t)(AtomicAdjust::get(mu->_requested_heap_size) - AtomicAdjust::get(mu->_total_heap_single_size) - AtomicAdjust::get(mu->_total_heap_array_size));
185#else
186 return 0;
187#endif
188}
189
190/**
191 * Returns the total number of bytes allocated from the virtual memory pool
192 * from code within Panda.
193 */
194INLINE size_t MemoryUsage::
196#ifdef DO_MEMORY_USAGE
197 return (size_t)AtomicAdjust::get(get_global_ptr()->_total_mmap_size);
198#else
199 return 0;
200#endif
201}
202
203/**
204 * Returns the total number of bytes of allocated memory in the heap that
205 * Panda didn't seem to be responsible for. This includes a few bytes for
206 * very low-level objects (like ConfigVariables) that cannot use Panda memory
207 * tracking because they are so very low-level.
208 *
209 * This also includes all of the memory that might have been allocated by a
210 * high-level interpreter, like Python.
211 *
212 * This number is only available if Panda is able to hook into the actual heap
213 * callback.
214 */
215INLINE size_t MemoryUsage::
217#ifdef DO_MEMORY_USAGE
218 MemoryUsage *mu = get_global_ptr();
219 if (mu->_count_memory_usage) {
220 // We can only possibly know this with memory counting, which tracks every
221 // malloc call.
222
223#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
224 // With alternative malloc, none of the Panda allocated memory shows up in
225 // total_size, so anything there is external.
226 return mu->_total_size;
227#else
228 // Without alternative malloc, the Panda allocated memory is also included
229 // in total_size, so we have to subtract it out.
230 return mu->_total_size - (size_t)mu->_total_heap_single_size - (size_t)mu->_total_heap_array_size;
231#endif
232 } else {
233 return 0;
234 }
235#else
236 return 0;
237#endif
238}
239
240/**
241 * Returns the total size of allocated memory consumed by the process, as
242 * nearly as can be determined.
243 */
244INLINE size_t MemoryUsage::
246#ifdef DO_MEMORY_USAGE
247 MemoryUsage *mu = get_global_ptr();
248 if (mu->_count_memory_usage) {
249 return mu->_total_size + (size_t)mu->_requested_heap_size;
250 } else {
251#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
252 return (size_t)mu->_requested_heap_size;
253#else
254 return (size_t)(AtomicAdjust::get(mu->_total_heap_single_size) + AtomicAdjust::get(mu->_total_heap_array_size));
255#endif
256 }
257#else
258 return 0;
259#endif
260}
261
262/**
263 * Returns the number of pointers currently active.
264 */
267#ifdef DO_MEMORY_USAGE
268 return get_global_ptr()->ns_get_num_pointers();
269#else
270 return 0;
271#endif
272}
273
274/**
275 * Fills the indicated MemoryUsagePointers with the set of all pointers
276 * currently active.
277 */
278INLINE void MemoryUsage::
280#ifdef DO_MEMORY_USAGE
281 get_global_ptr()->ns_get_pointers(result);
282#endif
283}
284
285/**
286 * Fills the indicated MemoryUsagePointers with the set of all pointers of the
287 * indicated type currently active.
288 */
289INLINE void MemoryUsage::
291#ifdef DO_MEMORY_USAGE
292 get_global_ptr()->ns_get_pointers_of_type(result, type);
293#endif
294}
295
296/**
297 * Fills the indicated MemoryUsagePointers with the set of all pointers that
298 * were allocated within the range of the indicated number of seconds ago.
299 */
300INLINE void MemoryUsage::
301get_pointers_of_age(MemoryUsagePointers &result, double from, double to) {
302#ifdef DO_MEMORY_USAGE
303 get_global_ptr()->ns_get_pointers_of_age(result, from, to);
304#endif
305}
306
307/**
308 * Fills the indicated MemoryUsagePointers with the set of all currently
309 * active pointers (that is, pointers allocated since the last call to
310 * freeze(), and not yet freed) that have a zero reference count.
311 *
312 * Generally, an undeleted pointer with a zero reference count means its
313 * reference count has never been incremented beyond zero (since once it has
314 * been incremented, the only way it can return to zero would free the
315 * pointer). This may include objects that are allocated statically or on the
316 * stack, which are never intended to be deleted. Or, it might represent a
317 * programmer or compiler error.
318 *
319 * This function has the side-effect of incrementing each of their reference
320 * counts by one, thus preventing them from ever being freed--but since they
321 * hadn't been freed anyway, probably no additional harm is done.
322 */
323INLINE void MemoryUsage::
325#ifdef DO_MEMORY_USAGE
326 get_global_ptr()->ns_get_pointers_with_zero_count(result);
327#endif
328}
329
330/**
331 * 'Freezes' all pointers currently stored so that they are no longer
332 * reported; only newly allocate pointers from this point on will appear in
333 * future information requests. This makes it easier to differentiate between
334 * continuous leaks and one-time memory allocations.
335 */
336INLINE void MemoryUsage::
337freeze() {
338#ifdef DO_MEMORY_USAGE
339 get_global_ptr()->ns_freeze();
340#endif
341}
342
343/**
344 * Shows the breakdown of types of all of the active pointers.
345 */
346INLINE void MemoryUsage::
348#ifdef DO_MEMORY_USAGE
349 get_global_ptr()->ns_show_current_types();
350#endif
351}
352
353/**
354 * Shows the breakdown of types of all of the pointers allocated and freed
355 * since the last call to freeze().
356 */
357INLINE void MemoryUsage::
359#ifdef DO_MEMORY_USAGE
360 get_global_ptr()->ns_show_trend_types();
361#endif
362}
363
364/**
365 * Shows the breakdown of ages of all of the active pointers.
366 */
367INLINE void MemoryUsage::
369#ifdef DO_MEMORY_USAGE
370 get_global_ptr()->ns_show_current_ages();
371#endif
372}
373
374/**
375 * Shows the breakdown of ages of all of the pointers allocated and freed
376 * since the last call to freeze().
377 */
378INLINE void MemoryUsage::
380#ifdef DO_MEMORY_USAGE
381 get_global_ptr()->ns_show_trend_ages();
382#endif
383}
384
385/**
386 * Returns the pointer to the only MemoryUsage object in the world.
387 */
388INLINE MemoryUsage *MemoryUsage::
389get_global_ptr() {
390#ifdef DO_MEMORY_USAGE
391#ifdef __GNUC__
392 // Tell the compiler that this is an unlikely branch.
393 if (__builtin_expect(_global_ptr == nullptr, 0)) {
394#else
395 if (_global_ptr == nullptr) {
396#endif
397 init_memory_usage();
398 }
399
400 return _global_ptr;
401#else
402 return nullptr;
403#endif
404}
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
This is a list of pointers returned by a MemoryUsage object in response to some query.
This class is used strictly for debugging purposes, specifically for tracking memory leaks of referen...
Definition: memoryUsage.h:35
static void show_current_types()
Shows the breakdown of types of all of the active pointers.
Definition: memoryUsage.I:347
static void get_pointers_of_age(MemoryUsagePointers &result, double from, double to)
Fills the indicated MemoryUsagePointers with the set of all pointers that were allocated within the r...
Definition: memoryUsage.I:301
static void get_pointers(MemoryUsagePointers &result)
Fills the indicated MemoryUsagePointers with the set of all pointers currently active.
Definition: memoryUsage.I:279
get_current_cpp_size
Returns the total number of bytes of allocated memory consumed by C++ objects, not including the memo...
Definition: memoryUsage.h:95
static void show_current_ages()
Shows the breakdown of ages of all of the active pointers.
Definition: memoryUsage.I:368
get_external_size
Returns the total number of bytes of allocated memory in the heap that Panda didn't seem to be respon...
Definition: memoryUsage.h:102
get_panda_mmap_size
Returns the total number of bytes allocated from the virtual memory pool from code within Panda.
Definition: memoryUsage.h:101
static void show_trend_types()
Shows the breakdown of types of all of the pointers allocated and freed since the last call to freeze...
Definition: memoryUsage.I:358
get_panda_heap_array_size
Returns the total number of bytes allocated from the heap from code within Panda, for arrays.
Definition: memoryUsage.h:99
static void record_pointer(ReferenceCount *ptr)
Indicates that the given pointer has been recently allocated.
Definition: memoryUsage.I:32
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
get_total_size
Returns the total size of allocated memory consumed by the process, as nearly as can be determined.
Definition: memoryUsage.h:103
static void freeze()
'Freezes' all pointers currently stored so that they are no longer reported; only newly allocate poin...
Definition: memoryUsage.I:337
get_panda_heap_single_size
Returns the total number of bytes allocated from the heap from code within Panda, for individual obje...
Definition: memoryUsage.h:98
static void get_pointers_with_zero_count(MemoryUsagePointers &result)
Fills the indicated MemoryUsagePointers with the set of all currently active pointers (that is,...
Definition: memoryUsage.I:324
static void get_pointers_of_type(MemoryUsagePointers &result, TypeHandle type)
Fills the indicated MemoryUsagePointers with the set of all pointers of the indicated type currently ...
Definition: memoryUsage.I:290
get_total_cpp_size
Returns the total number of bytes of allocated memory consumed by C++ objects, including the memory p...
Definition: memoryUsage.h:96
is_counting
Returns true if the MemoryUsage object is currently at least counting memory (e.g.
Definition: memoryUsage.h:94
static int get_num_pointers()
Returns the number of pointers currently active.
Definition: memoryUsage.I:266
static bool get_track_memory_usage()
Returns true if the user has Configured the variable 'track-memory-usage' to true,...
Definition: memoryUsage.I:20
static void remove_pointer(ReferenceCount *ptr)
Indicates that the given pointer has been recently freed.
Definition: memoryUsage.I:90
get_panda_heap_overhead
Returns the extra bytes allocated from the system that are not immediately used for holding allocated...
Definition: memoryUsage.h:100
static void show_trend_ages()
Shows the breakdown of ages of all of the pointers allocated and freed since the last call to freeze(...
Definition: memoryUsage.I:379
is_tracking
Returns true if the MemoryUsage object is currently tracking memory (e.g.
Definition: memoryUsage.h:93
A base class for all things that want to be reference-counted.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This is an abstract class that all classes which use TypeHandle, and also provide virtual functions t...
Definition: typedObject.h:88