mallocTag.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_TF_MALLOC_TAG_H
25 #define PXR_BASE_TF_MALLOC_TAG_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/base/tf/api.h"
29 
30 #include <atomic>
31 #include <cstdlib>
32 #include <cstdint>
33 #include <iosfwd>
34 #include <string>
35 #include <vector>
36 
37 PXR_NAMESPACE_OPEN_SCOPE
38 
41 
42 struct Tf_MallocPathNode;
43 
50 class TfMallocTag {
51 public:
52  struct CallStackInfo;
53 
60  struct CallTree {
80  struct PathNode {
81  size_t nBytes,
82  nBytesDirect;
83  size_t nAllocations;
84  std::string siteName;
85  std::vector<PathNode>
87  };
88 
97  struct CallSite {
98  std::string name;
99  size_t nBytes;
100  };
101 
102  // Note: enum below must be kept in sync with tfmodule/mallocCallTree.h
103 
106  TREE = 0,
109  };
110 
131  TF_API
132  std::string GetPrettyPrintString(PrintSetting setting = BOTH,
133  size_t maxPrintedNodes = 100000) const;
134 
140  TF_API
141  void Report(
142  std::ostream &out,
143  const std::string &rootName) const;
144 
146  TF_API
147  void Report(
148  std::ostream &out) const;
149 
151  std::vector<CallSite> callSites;
152 
155 
157  std::vector<CallStackInfo> capturedCallStacks;
158  };
159 
164  {
166  std::vector<uintptr_t> stack;
167 
170  size_t size;
171 
175  };
176 
188  TF_API static bool Initialize(std::string* errMsg);
189 
194  static bool IsInitialized() {
195  return TfMallocTag::_isInitialized;
196  }
197 
203  TF_API static size_t GetTotalBytes();
204 
210  TF_API static size_t GetMaxTotalBytes();
211 
224  TF_API static bool GetCallTree(CallTree* tree, bool skipRepeated = true);
225 
226 private:
227 
228  struct _ThreadData;
229 
230 public:
231 
255  class Auto {
256  public:
257  Auto(const Auto &) = delete;
258  Auto& operator=(const Auto &) = delete;
259 
260  Auto(Auto &&) = delete;
261  Auto& operator=(Auto &&) = delete;
262 
280  template <class Str, class... Strs>
281  explicit Auto(Str &&name1, Strs &&... nameN)
282  : _threadData(TfMallocTag::_Push(_CStr(std::forward<Str>(name1))))
283  , _nTags(_threadData
284  ? 1 + _PushImpl(std::forward<Strs>(nameN)...)
285  : 0) {}
286 
297  inline void Release() {
298  while (_nTags--) {
299  TfMallocTag::_End(_threadData);
300  }
301  _threadData = nullptr;
302  }
303 
309  inline ~Auto() {
310  Release();
311  }
312 
313  private:
314 
315  char const *_CStr(char const *cstr) const { return cstr; }
316  char const *_CStr(std::string const &str) const { return str.c_str(); }
317 
318  template <class Str, class... Strs>
319  int _PushImpl(Str &&tag, Strs &&... rest) {
320  TfMallocTag::_Begin(_CStr(std::forward<Str>(tag)), _threadData);
321  return 1 + _PushImpl(std::forward<Strs>(rest)...);
322  }
323 
324  int _PushImpl() {
325  // Recursion termination base-case.
326  return 0;
327  }
328 
329  _ThreadData* _threadData;
330  int _nTags;
331 
332  friend class TfMallocTag;
333  };
334 
335  // A historical compatibility: before Auto could accept only one argument,
336  // so Auto2 existed to handle two arguments. Now Auto can accept any number
337  // of arguments, so Auto2 is just an alias for Auto.
338  using Auto2 = Auto;
339 
349  static void Push(const std::string& name) {
350  _Push(name.c_str());
351  }
352 
354  static void Push(const char* name) {
355  _Push(name);
356  }
357 
363  static void Pop() {
364  if (TfMallocTag::_isInitialized) {
365  _End();
366  }
367  }
368 
386  TF_API static void SetDebugMatchList(const std::string& matchList);
387 
409  TF_API static void SetCapturedMallocStacksMatchList(const std::string& matchList);
410 
416  TF_API static std::vector<std::vector<uintptr_t> > GetCapturedMallocStacks();
417 
418 private:
419  friend struct _TemporaryDisabler;
420 
421  friend struct Tf_MallocGlobalData;
422 
423  static bool _Initialize(std::string* errMsg);
424 
425  static inline _ThreadData *_Push(char const *name) {
426  if (TfMallocTag::_isInitialized) {
427  return _Begin(name);
428  }
429  return nullptr;
430  }
431 
432  TF_API static _ThreadData *_Begin(char const *name,
433  _ThreadData *threadData = nullptr);
434  TF_API static void _End(_ThreadData *threadData = nullptr);
435 
436  static void* _MallocWrapper(size_t, const void*);
437  static void* _ReallocWrapper(void*, size_t, const void*);
438  static void* _MemalignWrapper(size_t, size_t, const void*);
439  static void _FreeWrapper(void*, const void*);
440 
441  friend class TfMallocTag::Auto;
442  class Tls;
443  friend class TfMallocTag::Tls;
444  TF_API static std::atomic<bool> _isInitialized;
445 };
446 
449 
452 
486 //
487 PXR_NAMESPACE_CLOSE_SCOPE
488 
489 #define TF_MALLOC_TAG_NEW(name1, name2) \
490  /* this is for STL purposes */ \
491  inline void* operator new(::std::size_t, void* ptr) { \
492  return ptr; \
493  } \
494  \
495  inline void* operator new(::std::size_t s) { \
496  PXR_NS::TfAutoMallocTag tag(name1, name2); \
497  return malloc(s); \
498  } \
499  \
500  inline void* operator new[](::std::size_t s) { \
501  PXR_NS::TfAutoMallocTag tag(name1, name2); \
502  return malloc(s); \
503  } \
504  \
505  /* Required due to the placement-new override above. */ \
506  inline void operator delete(void* ptr, void* place) {} \
507  \
508  inline void operator delete(void* ptr, size_t) { \
509  free(ptr); \
510  } \
511  \
512  inline void operator delete[] (void* ptr, size_t) { \
513  free(ptr); \
514  } \
515 
516 #endif
static void Push(const char *name)
Definition: mallocTag.h:354
Summary data structure for malloc statistics.
Definition: mallocTag.h:60
static TF_API size_t GetTotalBytes()
Return total number of allocated bytes.
This struct is used to represent a call stack taken for an allocation that was billed under a specifi...
Definition: mallocTag.h:163
size_t nAllocations
The number of allocations for this node.
Definition: mallocTag.h:83
void Release()
Pop the tag from the stack before it is destructed.
Definition: mallocTag.h:297
TF_API void Report(std::ostream &out, const std::string &rootName) const
Generates a report to the ostream out.
size_t nBytes
Allocated bytes by this or descendant nodes.
Definition: mallocTag.h:81
static TF_API bool GetCallTree(CallTree *tree, bool skipRepeated=true)
Return a snapshot of memory usage.
size_t size
The amount of allocated memory (accumulated over all allocations sharing this call stack).
Definition: mallocTag.h:170
Print both tree and call sites.
Definition: mallocTag.h:108
std::vector< CallStackInfo > capturedCallStacks
The captured malloc stacks.
Definition: mallocTag.h:157
std::vector< uintptr_t > stack
The stack frame pointers.
Definition: mallocTag.h:166
std::vector< CallSite > callSites
All call sites.
Definition: mallocTag.h:151
std::string name
Tag name.
Definition: mallocTag.h:98
PathNode root
Root node of the call-site hierarchy.
Definition: mallocTag.h:154
Print the full call tree.
Definition: mallocTag.h:106
static TF_API void SetDebugMatchList(const std::string &matchList)
Sets the tags to trap in the debugger.
Print just the call sites > 0.1%.
Definition: mallocTag.h:107
static void Pop()
Manually pop a tag from the stack.
Definition: mallocTag.h:363
static TF_API void SetCapturedMallocStacksMatchList(const std::string &matchList)
Sets the tags to trace.
Scoped (i.e.
Definition: mallocTag.h:255
PrintSetting
Specify which parts of the report to print.
Definition: mallocTag.h:105
Auto(Str &&name1, Strs &&... nameN)
Push one or more memory tags onto the local-call stack with names name1 ...
Definition: mallocTag.h:281
std::string siteName
Tag name.
Definition: mallocTag.h:84
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...
std::vector< PathNode > children
Children nodes.
Definition: mallocTag.h:86
Top-down memory tagging system.
Definition: mallocTag.h:50
static bool IsInitialized()
Return true if the tagging system is active.
Definition: mallocTag.h:194
static void Push(const std::string &name)
Manually push a tag onto the stack.
Definition: mallocTag.h:349
size_t numAllocations
The number of allocations (always one unless stack frames have been combined to create unique stacks)...
Definition: mallocTag.h:174
size_t nBytesDirect
Allocated bytes (only for this node).
Definition: mallocTag.h:81
static TF_API size_t GetMaxTotalBytes()
Return the maximum total number of bytes that have ever been allocated at one time.
Node in the call tree structure.
Definition: mallocTag.h:80
Record of the bytes allocated under each different tag.
Definition: mallocTag.h:97
static TF_API bool Initialize(std::string *errMsg)
Initialize the memory tagging system.
TF_API std::string GetPrettyPrintString(PrintSetting setting=BOTH, size_t maxPrintedNodes=100000) const
Return the malloc report string.
~Auto()
Pop a memory tag from the local-call stack.
Definition: mallocTag.h:309