All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 TF_MALLOCTAG_H
25 #define TF_MALLOCTAG_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/base/tf/api.h"
29 
30 #include <cstdlib>
31 #include <iosfwd>
32 #include <stdint.h>
33 #include <string>
34 #include <vector>
35 
36 PXR_NAMESPACE_OPEN_SCOPE
37 
40 
41 struct Tf_MallocPathNode;
42 
49 class TfMallocTag {
50 public:
51  struct CallStackInfo;
52 
59  struct CallTree {
79  struct PathNode {
80  size_t nBytes,
81  nBytesDirect;
82  size_t nAllocations;
83  std::string siteName;
84  std::vector<PathNode>
86  };
87 
96  struct CallSite {
97  std::string name;
98  size_t nBytes;
99  };
100 
101  // Note: enum below must be kept in sync with tfmodule/mallocCallTree.h
102 
105  TREE = 0,
108  };
109 
130  TF_API
131  std::string GetPrettyPrintString(PrintSetting setting = BOTH,
132  size_t maxPrintedNodes = 100000) const;
133 
139  TF_API
140  void Report(
141  std::ostream &out,
142  const std::string &rootName) const;
143 
145  TF_API
146  void Report(
147  std::ostream &out) const;
148 
150  std::vector<CallSite> callSites;
151 
154 
156  std::vector<CallStackInfo> capturedCallStacks;
157  };
158 
163  {
165  std::vector<uintptr_t> stack;
166 
169  size_t size;
170 
174  };
175 
187  TF_API static bool Initialize(std::string* errMsg);
188 
193  static bool IsInitialized() {
194  return TfMallocTag::_doTagging;
195  }
196 
202  TF_API static size_t GetTotalBytes();
203 
209  TF_API static size_t GetMaxTotalBytes();
210 
223  TF_API static bool GetCallTree(CallTree* tree, bool skipRepeated = true);
224 
225 private:
226  // Enum describing whether allocations are being tagged in an associated
227  // thread.
228  enum _Tagging {
229  _TaggingEnabled, // Allocations are being tagged
230  _TaggingDisabled, // Allocations are not being tagged
231 
232  _TaggingDormant // Tagging has not been initialized in this
233  // thread as no malloc tags have been pushed onto
234  // the stack.
235  };
236 
237  struct _ThreadData;
238 
239 public:
240 
262  class Auto {
263  public:
264  Auto(const Auto &) = delete;
265  Auto& operator=(const Auto &) = delete;
266 
267  Auto(Auto &&) = delete;
268  Auto& operator=(Auto &&) = delete;
269 
281  Auto(const char* name) : _threadData(0) {
282  if (TfMallocTag::_doTagging)
283  _Begin(name);
284  }
285 
302  Auto(const std::string& name) : _threadData(0) {
303  if (TfMallocTag::_doTagging)
304  _Begin(name);
305  }
306 
317  inline void Release() {
318  if (_threadData) {
319  _End();
320  _threadData = NULL;
321  }
322  }
323 
329  inline ~Auto() {
330  Release();
331  }
332 
333  private:
334  TF_API void _Begin(const char* name);
335  TF_API void _Begin(const std::string& name);
336  TF_API void _End();
337 
338  _ThreadData* _threadData;
339 
340  friend class TfMallocTag;
341  };
342 
349  class Auto2 {
350  public:
354  Auto2(const char* name1, const char* name2) :
355  _tag1(name1),
356  _tag2(name2)
357  {
358  }
359 
363  Auto2(const std::string& name1, const std::string& name2) :
364  _tag1(name1),
365  _tag2(name2)
366  {
367  }
368 
372  void Release() {
373  _tag2.Release();
374  _tag1.Release();
375  }
376 
377  private:
378  Auto _tag1;
379  Auto _tag2;
380  };
381 
391  static void Push(const std::string& name) {
392  TfMallocTag::Auto noname(name);
393  noname._threadData = NULL; // disable destructor
394  }
395 
397  static void Push(const char* name) {
398  TfMallocTag::Auto noname(name);
399  noname._threadData = NULL; // disable destructor
400  }
401 
410  TF_API static void Pop(const char* name = NULL);
411 
413  static void Pop(const std::string& name) {
414  Pop(name.c_str());
415  }
416 
434  TF_API static void SetDebugMatchList(const std::string& matchList);
435 
457  TF_API static void SetCapturedMallocStacksMatchList(const std::string& matchList);
458 
464  TF_API static std::vector<std::vector<uintptr_t> > GetCapturedMallocStacks();
465 
466 private:
467  friend struct Tf_MallocGlobalData;
468 
469  class _TemporaryTaggingState {
470  public:
471  explicit _TemporaryTaggingState(_Tagging state);
472  ~_TemporaryTaggingState();
473 
474  _TemporaryTaggingState(const _TemporaryTaggingState &);
475  _TemporaryTaggingState& operator=(const _TemporaryTaggingState &);
476 
477  _TemporaryTaggingState(_TemporaryTaggingState &&);
478  _TemporaryTaggingState& operator=(_TemporaryTaggingState &&);
479 
480  private:
481  _Tagging _oldState;
482  };
483 
484  static void _SetTagging(_Tagging state);
485  static _Tagging _GetTagging();
486 
487  static bool _Initialize(std::string* errMsg);
488 
489  static inline bool _ShouldNotTag(_ThreadData**, _Tagging* t = NULL);
490  static inline Tf_MallocPathNode* _GetCurrentPathNodeNoLock(
491  const _ThreadData* threadData);
492 
493  static void* _MallocWrapper_ptmalloc(size_t, const void*);
494  static void* _ReallocWrapper_ptmalloc(void*, size_t, const void*);
495  static void* _MemalignWrapper_ptmalloc(size_t, size_t, const void*);
496  static void _FreeWrapper_ptmalloc(void*, const void*);
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 bool _doTagging;
507 };
508 
511 
514 
548 //
549 PXR_NAMESPACE_CLOSE_SCOPE
550 
551 #define TF_MALLOC_TAG_NEW(name1, name2) \
552  /* this is for STL purposes */ \
553  inline void* operator new(::std::size_t, void* ptr) { \
554  return ptr; \
555  } \
556  \
557  inline void* operator new(::std::size_t s) { \
558  PXR_NS::TfAutoMallocTag tag1(name1); \
559  PXR_NS::TfAutoMallocTag tag2(name2); \
560  return malloc(s); \
561  } \
562  \
563  inline void* operator new[](::std::size_t s) { \
564  PXR_NS::TfAutoMallocTag tag1(name1); \
565  PXR_NS::TfAutoMallocTag tag2(name2); \
566  return malloc(s); \
567  } \
568  \
569  /* Required due to the placement-new override above. */ \
570  inline void operator delete(void* ptr, void* place) {} \
571  \
572  inline void operator delete(void* ptr, size_t) { \
573  free(ptr); \
574  } \
575  \
576  inline void operator delete[] (void* ptr, size_t) { \
577  free(ptr); \
578  } \
579 
580 #endif
static void Push(const char *name)
Definition: mallocTag.h:397
Summary data structure for malloc statistics.
Definition: mallocTag.h:59
Auto2(const char *name1, const char *name2)
Push two memory tags onto the local-call stack.
Definition: mallocTag.h:354
static TF_API void Pop(const char *name=NULL)
Manually pop a tag from the stack.
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:162
size_t nAllocations
The number of allocations for this node.
Definition: mallocTag.h:82
void Release()
Pop the tag from the stack before it is destructed.
Definition: mallocTag.h:317
Auto(const char *name)
Push a memory tag onto the local-call stack with name name.
Definition: mallocTag.h:281
size_t nBytes
Allocated bytes by this or descendant nodes.
Definition: mallocTag.h:80
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:169
Print both tree and call sites.
Definition: mallocTag.h:107
std::vector< CallStackInfo > capturedCallStacks
The captured malloc stacks.
Definition: mallocTag.h:156
Scoped (i.e.
Definition: mallocTag.h:349
TF_API std::string GetPrettyPrintString(PrintSetting setting=BOTH, size_t maxPrintedNodes=100000) const
Return the malloc report string.
std::vector< uintptr_t > stack
The stack frame pointers.
Definition: mallocTag.h:165
TF_API void Report(std::ostream &out, const std::string &rootName) const
Generates a report to the ostream out.
std::vector< CallSite > callSites
All call sites.
Definition: mallocTag.h:150
std::string name
Tag name.
Definition: mallocTag.h:97
void Release()
Pop two memory tags from the local-call stack.
Definition: mallocTag.h:372
PathNode root
Root node of the call-site hierarchy.
Definition: mallocTag.h:153
Print the full call tree.
Definition: mallocTag.h:105
static TF_API void SetDebugMatchList(const std::string &matchList)
Sets the tags to trap in the debugger.
Print just the call sites &gt; 0.1%.
Definition: mallocTag.h:106
TfMallocTag::Auto2 TfAutoMallocTag2
Top-down memory tagging system.
Definition: mallocTag.h:513
static TF_API void SetCapturedMallocStacksMatchList(const std::string &matchList)
Sets the tags to trace.
Scoped (i.e.
Definition: mallocTag.h:262
PrintSetting
Specify which parts of the report to print.
Definition: mallocTag.h:104
std::string siteName
Tag name.
Definition: mallocTag.h:83
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:85
Auto(const std::string &name)
Push a memory tag onto the local-call stack with name name.
Definition: mallocTag.h:302
TfMallocTag::Auto TfAutoMallocTag
Top-down memory tagging system.
Definition: mallocTag.h:510
Top-down memory tagging system.
Definition: mallocTag.h:49
static bool IsInitialized()
Return true if the tagging system is active.
Definition: mallocTag.h:193
static void Push(const std::string &name)
Manually push a tag onto the stack.
Definition: mallocTag.h:391
static void Pop(const std::string &name)
Definition: mallocTag.h:413
size_t numAllocations
The number of allocations (always one unless stack frames have been combined to create unique stacks)...
Definition: mallocTag.h:173
size_t nBytesDirect
Allocated bytes (only for this node).
Definition: mallocTag.h:80
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:79
Record of the bytes allocated under each different tag.
Definition: mallocTag.h:96
Auto2(const std::string &name1, const std::string &name2)
Push two memory tags onto the local-call stack.
Definition: mallocTag.h:363
static TF_API bool Initialize(std::string *errMsg)
Initialize the memory tagging system.
~Auto()
Pop a memory tag from the local-call stack.
Definition: mallocTag.h:329