Loading...
Searching...
No Matches
mallocTag.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_MALLOC_TAG_H
8#define PXR_BASE_TF_MALLOC_TAG_H
9
10#include "pxr/pxr.h"
11#include "pxr/base/tf/api.h"
12#include "pxr/base/arch/hints.h"
13
14#include <atomic>
15#include <cstdlib>
16#include <cstdint>
17#include <iosfwd>
18#include <new>
19#include <string>
20#include <vector>
21
22PXR_NAMESPACE_OPEN_SCOPE
23
26
27struct Tf_MallocPathNode;
28
36public:
37 struct CallStackInfo;
38
45 struct CallTree {
65 struct PathNode {
66 size_t nBytes,
68 size_t nAllocations;
69 std::string siteName;
70 std::vector<PathNode>
72 };
73
82 struct CallSite {
83 std::string name;
84 size_t nBytes;
85 };
86
89 TREE = 0,
91 BOTH
92 };
93
94
97
118 TF_API
120 size_t maxPrintedNodes = 100000) const;
121
126 TF_API
127 void Report(
128 std::ostream &out,
129 const std::string &rootName) const;
130
132 TF_API
133 void Report(
134 std::ostream &out) const;
135
139 TF_API
141 std::istream &in);
142
144
145
147 std::vector<CallSite> callSites;
148
151
153 std::vector<CallStackInfo> capturedCallStacks;
154 };
155
160 {
162 std::vector<uintptr_t> stack;
163
166 size_t size;
167
171 };
172
184 TF_API static bool Initialize(std::string* errMsg);
185
190 static bool IsInitialized() {
191 return TfMallocTag::_isInitialized;
192 }
193
199 TF_API static size_t GetTotalBytes();
200
206 TF_API static size_t GetMaxTotalBytes();
207
220 TF_API static bool GetCallTree(CallTree* tree, bool skipRepeated = true);
221
222private:
223
224 struct _ThreadData;
225
226public:
227
251 class Auto {
252 public:
253 Auto(const Auto &) = delete;
254 Auto& operator=(const Auto &) = delete;
255
256 Auto(Auto &&) = delete;
257 Auto& operator=(Auto &&) = delete;
258
276 template <class Str, class... Strs>
277 explicit Auto(Str &&name1, Strs &&... nameN)
278 : _threadData(TfMallocTag::_Push(_CStr(std::forward<Str>(name1))))
279 , _nTags(_threadData ? 1 + sizeof...(Strs) : 0) {
280 if (_threadData) {
281 (..., TfMallocTag::_Begin(
282 _CStr(std::forward<Strs>(nameN)), _threadData));
283 }
284 }
285
296 inline void Release() {
297 if (_threadData) {
298 TfMallocTag::_End(_nTags, _threadData);
299 _threadData = nullptr;
300 }
301 }
302
308 inline ~Auto() {
309 Release();
310 }
311
312 private:
313
314 char const *_CStr(char const *cstr) const { return cstr; }
315 char const *_CStr(std::string const &str) const { return str.c_str(); }
316
317 _ThreadData* _threadData;
318 int _nTags;
319
320 friend class TfMallocTag;
321 };
322
323 // An historical compatibility: before Auto could accept only one argument,
324 // so Auto2 existed to handle two arguments. Now Auto can accept any number
325 // of arguments, so Auto2 is just an alias for Auto.
326 using Auto2 = Auto;
327
328 // fwd for friendship.
329 class StackOverride;
330
338 public:
339 StackState() = default;
340
341 private:
342 explicit StackState(Tf_MallocPathNode *top) : _top(top) {}
343
344 Tf_MallocPathNode *_top = nullptr;
345
346 friend class TfMallocTag;
347 friend class StackOverride;
348 };
349
363 public:
364 explicit StackOverride(StackState state)
365 : _state(state)
366 , _tls(state._top ? _Push() : nullptr) {}
367
368 // Noncopyable, nonmovable.
369 StackOverride(const StackOverride &) = delete;
370 StackOverride &operator=(const StackOverride &) = delete;
371
373 if (ARCH_UNLIKELY(_tls)) {
374 _Pop();
375 }
376 }
377
378 private:
379 TF_API _ThreadData *_Push() const;
380 TF_API void _Pop() const;
381
382 const StackState _state;
383 _ThreadData *_tls;
384
385 friend class TfMallocTag;
386 };
387
395 return ARCH_UNLIKELY(TfMallocTag::_isInitialized)
396 ? _GetCurrentStackState() : StackState {};
397 }
398
408 static void Push(const std::string& name) {
409 _Push(name.c_str());
410 }
411
413 static void Push(const char* name) {
414 _Push(name);
415 }
416
422 static void Pop() {
423 if (TfMallocTag::_isInitialized) {
424 _End();
425 }
426 }
427
445 TF_API static void SetDebugMatchList(const std::string& matchList);
446
468 TF_API static void
469 SetCapturedMallocStacksMatchList(const std::string& matchList);
470
476 TF_API static std::vector<std::vector<uintptr_t> > GetCapturedMallocStacks();
477
478private:
479 friend struct _TemporaryDisabler;
480
481 friend struct Tf_MallocGlobalData;
482
483 static bool _Initialize(std::string* errMsg);
484
485 static inline _ThreadData *_Push(char const *name) {
486 if (TfMallocTag::_isInitialized) {
487 return _Begin(name);
488 }
489 return nullptr;
490 }
491
492 TF_API static _ThreadData *_Begin(char const *name,
493 _ThreadData *threadData = nullptr);
494 TF_API static void _End(int nTags = 1, _ThreadData *threadData = nullptr);
495
496 TF_API static StackState _GetCurrentStackState();
497
498 static void* _MallocWrapper(size_t, const void*);
499 static void* _ReallocWrapper(void*, size_t, const void*);
500 static void* _MemalignWrapper(size_t, size_t, const void*);
501 static void _FreeWrapper(void*, const void*);
502
503 friend class TfMallocTag::Auto;
504 class Tls;
505 friend class TfMallocTag::Tls;
506 TF_API static std::atomic<bool> _isInitialized;
507};
508
511
514
548//
549PXR_NAMESPACE_CLOSE_SCOPE
550
551#define TF_MALLOC_TAG_NEW(name1, name2) \
552 /* this is for STL purposes */ \
553 ARCH_ALWAYS_INLINE inline void* operator new(::std::size_t, void* ptr) { \
554 return ptr; \
555 } \
556 \
557 ARCH_ALWAYS_INLINE inline void* operator new(::std::size_t s) { \
558 PXR_NS::TfAutoMallocTag tag(name1, name2); \
559 return ::operator new(s, std::nothrow); \
560 } \
561 \
562 ARCH_ALWAYS_INLINE inline void* operator new[](::std::size_t s) { \
563 PXR_NS::TfAutoMallocTag tag(name1, name2); \
564 return ::operator new[](s, std::nothrow); \
565 } \
566 \
567 /* Required due to the placement-new override above. */ \
568 ARCH_ALWAYS_INLINE inline void operator delete(void* ptr, void* place) {} \
569 \
570 ARCH_ALWAYS_INLINE inline void operator delete(void* ptr, size_t) { \
571 ::operator delete(ptr, std::nothrow); \
572 } \
573 \
574 ARCH_ALWAYS_INLINE inline void operator delete[] (void* ptr, size_t) { \
575 ::operator delete[](ptr, std::nothrow); \
576 } \
577
578#endif
Scoped (i.e.
Definition: mallocTag.h:251
Auto(Str &&name1, Strs &&... nameN)
Push one or more memory tags onto the local-call stack with names name1 ... nameN.
Definition: mallocTag.h:277
~Auto()
Pop a memory tag from the local-call stack.
Definition: mallocTag.h:308
void Release()
Pop the tag from the stack before it is destructed.
Definition: mallocTag.h:296
An object that represents a snapshot of a thread's TfMallocTag stack state.
Definition: mallocTag.h:337
Top-down memory tagging system.
Definition: mallocTag.h:35
static void Push(const char *name)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: mallocTag.h:413
static TF_API void SetDebugMatchList(const std::string &matchList)
Sets the tags to trap in the debugger.
size_t numAllocations
The number of allocations (always one unless stack frames have been combined to create unique stacks)...
Definition: mallocTag.h:170
static StackState GetCurrentStackState()
Capture the current thread's TfMallocTag stack state and return it.
Definition: mallocTag.h:394
static TF_API std::vector< std::vector< uintptr_t > > GetCapturedMallocStacks()
Returns the captured malloc stack traces for allocations billed to the malloc tags passed to SetCaptu...
static TF_API void SetCapturedMallocStacksMatchList(const std::string &matchList)
Sets the tags to trace.
static void Push(const std::string &name)
Manually push a tag onto the stack.
Definition: mallocTag.h:408
std::vector< uintptr_t > stack
The stack frame pointers.
Definition: mallocTag.h:162
size_t size
The amount of allocated memory (accumulated over all allocations sharing this call stack).
Definition: mallocTag.h:166
static TF_API size_t GetTotalBytes()
Return total number of allocated bytes.
static TF_API bool Initialize(std::string *errMsg)
Initialize the memory tagging system.
static bool IsInitialized()
Return true if the tagging system is active.
Definition: mallocTag.h:190
static void Pop()
Manually pop a tag from the stack.
Definition: mallocTag.h:422
static TF_API bool GetCallTree(CallTree *tree, bool skipRepeated=true)
Return a snapshot of memory usage.
static TF_API size_t GetMaxTotalBytes()
Return the maximum total number of bytes that have ever been allocated at one time.
This struct is used to represent a call stack taken for an allocation that was billed under a specifi...
Definition: mallocTag.h:160
Compiler hints.
STL namespace.
Summary data structure for malloc statistics.
Definition: mallocTag.h:45
std::vector< PathNode > children
Children nodes.
Definition: mallocTag.h:71
TF_API std::string GetPrettyPrintString(PrintSetting setting=BOTH, size_t maxPrintedNodes=100000) const
Return the malloc report string.
size_t nAllocations
The number of allocations for this node.
Definition: mallocTag.h:68
std::string siteName
Tag name.
Definition: mallocTag.h:69
std::vector< CallStackInfo > capturedCallStacks
The captured malloc stacks.
Definition: mallocTag.h:153
size_t nBytes
Mem allocated including descendant nodes.
Definition: mallocTag.h:66
TF_API void Report(std::ostream &out) const
Generates a report to the ostream out.
size_t nBytesDirect
Mem allocated excluding descendant nodes.
Definition: mallocTag.h:67
std::string name
Tag name.
Definition: mallocTag.h:83
PrintSetting
Specify which parts of the report to print.
Definition: mallocTag.h:88
@ BOTH
Print both tree and call sites.
Definition: mallocTag.h:91
@ TREE
Print the full call tree.
Definition: mallocTag.h:89
@ CALLSITES
Print just the call sites > 0.1%.
Definition: mallocTag.h:90
PathNode root
Root node of the call-site hierarchy.
Definition: mallocTag.h:150
TF_API void Report(std::ostream &out, const std::string &rootName) const
Generates a report to the ostream out.
TF_API bool LoadReport(std::istream &in)
Load the contents of in into the root of the call tree.
std::vector< CallSite > callSites
All call sites.
Definition: mallocTag.h:147
Record of the bytes allocated under each different tag.
Definition: mallocTag.h:82
Node in the call tree structure.
Definition: mallocTag.h:65