HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDGE_DebugUtils.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * COMMENTS:
7  */
8 
9 #ifndef __PDGE_DEBUG_UTILS_H__
10 #define __PDGE_DEBUG_UTILS_H__
11 
12 /**
13  * The following defines can be used to enable debugging utilities:
14  *
15  * PDGE_DEBUG_ENABLE_LOGGING will enable a thread-specific that is collected
16  * and dumped to stdout when evaluation completes
17  *
18  * PDGE_DEBUG_ENABLE_DOT will enable a DOT graph print out at the end of
19  * evaluation. This graph become prohibitively complicated for large
20  * dependency graphs and the DOT layout engine may struggle to correctly
21  * display it.
22  *
23  * PDGE_DEBUG_ENABLE_NAMES enables storage of string name identifiers on
24  * each dependency object. This is typically also enabled when enabling either
25  * PDGE_DEBUG_ENABLE_LOGGING or PDGE_DEBUG_ENABLE_DOT, otherwise the output
26  * of those is of limited use.
27  *
28  * PDGE_DEBUG_DELAY adds a delay to dependency resolution, putting the
29  * evaluator into "slow motion" to make it easier to observe execution
30  * order.
31  */
32 
33 //#define PDGE_DEBUG_ENABLE_LOGGING 1
34 //#define PDGE_DEBUG_ENABLE_DOT 1
35 //#define PDGE_DEBUG_ENABLE_NAMES 1
36 //#define PDGE_DEBUG_ENABLE_IDS 1
37 //#define PDGE_DEBUG_DELAY 500
38 
39 #include <UT/UT_Array.h>
40 #include <UT/UT_ArrayMap.h>
41 #include <UT/UT_ArraySet.h>
42 #include <UT/UT_ConcurrentVector.h>
44 #include <UT/UT_StringHolder.h>
45 #include <UT/UT_SysClone.h>
46 #include <UT/UT_WorkBuffer.h>
47 
48 #include <SYS/SYS_AtomicInt.h>
49 
50 class PDGE_Dependency;
52 
53 /*
54  * Utility functions to debuging dependency graph evaluations. The
55  * functionality in this file is completely disabled when the PDGE_DEBUG
56  * defines are commented out.
57  *
58  * It currently offers three utilities to assist in debugging dependency
59  * graph evaluation:
60  *
61  * - A mechanism for adding an artificial delay to evaluation, to make it
62  * easier to observe evaluation sequencing.
63  * - A threaded log, which keeps messages in thread specific queues. The
64  * messages can be dumped after evaluation completes, including a thread
65  * id prefix on each message to track evaluation order.
66  * - A method for dumping a graph to the DOT format.
67  *
68  * Additionally, the PDGE_DEBUG_ENABLE_NAMES flag can be enabled so that
69  * all PDGE_Dependency objects store a string name for easier identification.
70  * When that flag is off, the code for storing the name is not built.
71  */
73 {
74 public:
75  /// Appends a message to a thread-safe log. Each thread stores its own
76  /// list of messages along with a unique id for each message. This
77  /// method expects a format string and variadic arg list, which are
78  /// handled using UT_Format.
79  template <typename... Args>
80  inline static void appendLog(const char* fmt, Args&&... args)
81  {
82  #ifdef PDGE_DEBUG_ENABLE_LOGGING
84  buffer.format(fmt,
85  std::forward<Args>(args)...);
86 
87  int id = SYSgetSTID();
88  auto&& log = myLog.getValueForThread(id);
89  log.append({buffer.buffer(),
90  myLogCounter.add(1), id});
91  #endif
92  }
93 
94  /// Adds a dependency to the tracking list. This method should be used
95  /// to inform the debug utils about depdendcies involved during
96  /// evaluation for the purpose of dumping a DOT graph.
97  inline static void addDependency(PDGE_Dependency* dependency)
98  {
99  #ifdef PDGE_DEBUG_ENABLE_DOT
100  myDependencies.push_back(dependency);
101  #endif
102  }
103 
104  /// Artificially delays dependency evaluation if the PDGE_DEBUG_DELAY
105  /// value is defined. The value is the number of milliseconds to spend
106  /// waiting for evaluations.
107  inline static void artificialDelay()
108  {
109  #ifdef PDGE_DEBUG_DELAY
110  UTnap(PDGE_DEBUG_DELAY);
111  #endif
112  }
113 
114  /// Returns a unique if for a dependency, if PDGE_DEBUG_ENABLE_IDS is on.
115  /// This is useful for DOT graph output as it can be used to reduce the
116  /// label size.
117  inline static int uniqueId()
118  {
119  #ifdef PDGE_DEBUG_ENABLE_IDS
120  return myIdCounter.add(1);
121  #else
122  return 0;
123  #endif
124  }
125 
126 
127  /// Dumps the contents of the log to stdout. Messages are sorted by their
128  /// unique ID and printed along with the thread ID from which they were
129  /// initially reported. When PDGE_DEBUG_ENABLE_LOGGING is not enabled
130  /// this method does nothing.
131  static void dumpLog();
132 
133  /// Dumps the recorded dependencies as a DOT graph to the specified
134  /// buffer. PDGE_DEBUG_ENABLE_NAMES should be enabled so that the DOT
135  /// graph has useful labels. When PDGE_DEBUG_ENABLE_DOT is not enabled
136  /// this method does nothing.
137  static void dumpDOT(UT_WorkBuffer& buffer);
138 
139 private:
140  struct Message
141  {
142  UT_StringHolder myMessage;
143  int myIndex;
144  int myId;
145 
146  static bool sort(const Message& a, const Message& b)
147  { return (a.myIndex < b.myIndex); }
148  };
149 
150  using DepList = UT_ConcurrentVector<PDGE_Dependency*>;
151  using EdgeMap = UT_ArrayMap<PDGE_Dependency*,
153  using LogArray = UT_Array<Message>;
154  using ThreadedLog = UT_ThreadSpecificValue<LogArray>;
155 
156 
157 private:
158  static void dumpDOT(UT_WorkBuffer& buffer,
159  PDGE_Dependency* dependency,
160  EdgeMap& exclusion_map);
161 
162 private:
163 
164 #ifdef PDGE_DEBUG_ENABLE_DOT
165  static DepList myDependencies;
166 #endif
167 
168 #ifdef PDGE_DEBUG_ENABLE_LOGGING
169  static ThreadedLog myLog;
170  static SYS_AtomicInt32 myLogCounter;
171 #endif
172 
173 #ifdef PDGE_DEBUG_ENABLE_IDS
174  static SYS_AtomicInt32 myIdCounter;
175 #endif
176 };
177 
178 #endif
static void addDependency(PDGE_Dependency *dependency)
static void artificialDelay()
SYS_FORCE_INLINE const char * buffer() const
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
static int uniqueId()
static void appendLog(const char *fmt, Args &&...args)
GLuint buffer
Definition: glcorearb.h:660
Definition: core.h:760
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
static void dumpLog()
static void dumpDOT(UT_WorkBuffer &buffer)
size_t format(const char *fmt, const Args &...args)
SYS_API int SYSgetSTID()
**If you just want to fire and args
Definition: thread.h:609
OIIO_FORCEINLINE T log(const T &v)
Definition: simd.h:7688
void sort(I begin, I end, const Pred &pred)
Definition: pugixml.cpp:7334