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  */
19 ALWAYS_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  */
31 INLINE 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  */
41 INLINE void MemoryUsage::
42 record_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  */
54 INLINE 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  */
67 INLINE void MemoryUsage::
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  */
79 INLINE void MemoryUsage::
80 update_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  */
89 INLINE 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  */
100 INLINE bool MemoryUsage::
101 is_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  */
114 INLINE bool MemoryUsage::
115 is_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  */
127 INLINE size_t MemoryUsage::
128 get_current_cpp_size() {
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  */
140 INLINE size_t MemoryUsage::
141 get_total_cpp_size() {
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  */
153 INLINE size_t MemoryUsage::
154 get_panda_heap_single_size() {
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  */
166 INLINE size_t MemoryUsage::
167 get_panda_heap_array_size() {
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  */
180 INLINE size_t MemoryUsage::
181 get_panda_heap_overhead() {
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  */
194 INLINE size_t MemoryUsage::
195 get_panda_mmap_size() {
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  */
215 INLINE size_t MemoryUsage::
216 get_external_size() {
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  */
244 INLINE size_t MemoryUsage::
245 get_total_size() {
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  */
265 INLINE int MemoryUsage::
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  */
278 INLINE 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  */
289 INLINE 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  */
300 INLINE void MemoryUsage::
301 get_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  */
323 INLINE 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  */
336 INLINE void MemoryUsage::
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  */
346 INLINE 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  */
357 INLINE 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  */
367 INLINE 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  */
378 INLINE 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  */
388 INLINE MemoryUsage *MemoryUsage::
389 get_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 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
This is an abstract class that all classes which use TypeHandle, and also provide virtual functions t...
Definition: typedObject.h:88
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
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
static int get_num_pointers()
Returns the number of pointers currently active.
Definition: memoryUsage.I:266
static void get_pointers(MemoryUsagePointers &result)
Fills the indicated MemoryUsagePointers with the set of all pointers currently active.
Definition: memoryUsage.I:279
This is a list of pointers returned by a MemoryUsage object in response to some query.
static void remove_pointer(ReferenceCount *ptr)
Indicates that the given pointer has been recently freed.
Definition: memoryUsage.I:90
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
static void freeze()
'Freezes' all pointers currently stored so that they are no longer reported; only newly allocate poin...
Definition: memoryUsage.I:337
This class is used strictly for debugging purposes, specifically for tracking memory leaks of referen...
Definition: memoryUsage.h:35
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
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
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
A base class for all things that want to be reference-counted.
static void show_current_types()
Shows the breakdown of types of all of the active pointers.
Definition: memoryUsage.I:347
static void show_current_ages()
Shows the breakdown of ages of all of the active pointers.
Definition: memoryUsage.I:368
static bool get_track_memory_usage()
Returns true if the user has Configured the variable 'track-memory-usage' to true,...
Definition: memoryUsage.I:20
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
static void record_pointer(ReferenceCount *ptr)
Indicates that the given pointer has been recently allocated.
Definition: memoryUsage.I:32