Advertisement
Guest User

Untitled

a guest
Oct 20th, 2019
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.01 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <assert.h>
  4.  
  5. #include "Output.h"
  6.  
  7. namespace NULLCTime
  8. {
  9. void clockMicroInit();
  10. unsigned clockMicro();
  11. }
  12.  
  13. namespace NULLC
  14. {
  15. template<typename T>
  16. struct TraceArray
  17. {
  18. TraceArray(unsigned size)
  19. {
  20. count = 0;
  21. max = size;
  22. data = new T[size];
  23. }
  24.  
  25. ~TraceArray()
  26. {
  27. delete[] data;
  28. }
  29.  
  30. unsigned count;
  31. unsigned max;
  32. T *data;
  33. };
  34.  
  35. struct TraceScopeToken
  36. {
  37. TraceScopeToken()
  38. {
  39. category = "";
  40. name = "";
  41. }
  42.  
  43. TraceScopeToken(const char *category, const char *name) : category(category), name(name)
  44. {
  45. }
  46.  
  47. const char *category;
  48. const char *name;
  49. };
  50.  
  51. struct TraceEvent
  52. {
  53. unsigned isEnter : 1;
  54. unsigned isLabel : 1;
  55. unsigned token : 30;
  56.  
  57. unsigned ts;
  58. };
  59.  
  60. void TraceDump();
  61.  
  62. struct TraceContext
  63. {
  64. TraceContext(): scopeTokens(4096), labels(262144), events(262144), outputBuf(32768), tempBuf(1024)
  65. {
  66. output.stream = output.openStream("trace.json");
  67.  
  68. output.outputBuf = outputBuf.data;
  69. output.outputBufSize = outputBuf.max;
  70.  
  71. output.tempBuf = tempBuf.data;
  72. output.tempBufSize = tempBuf.max;
  73.  
  74. output.Print('[');
  75.  
  76. needComma = false;
  77. openEvent = false;
  78. depth = 0;
  79. outputDepth = 0;
  80. }
  81.  
  82. ~TraceContext()
  83. {
  84. TraceDump();
  85.  
  86. output.Print(']');
  87. output.Flush();
  88.  
  89. output.closeStream(output.stream);
  90. output.stream = NULL;
  91. }
  92.  
  93. OutputContext output;
  94.  
  95. bool needComma;
  96. bool openEvent;
  97. unsigned depth;
  98. unsigned outputDepth;
  99.  
  100. TraceArray<TraceScopeToken> scopeTokens;
  101. TraceArray<char> labels;
  102.  
  103. TraceArray<TraceEvent> events;
  104.  
  105. TraceArray<char> outputBuf;
  106. TraceArray<char> tempBuf;
  107. };
  108.  
  109. extern TraceContext *traceContext;
  110.  
  111. inline TraceContext* TraceGetContext()
  112. {
  113. static TraceContext context;
  114.  
  115. NULLCTime::clockMicroInit();
  116.  
  117. return &context;
  118. }
  119.  
  120. inline unsigned TraceGetToken(const char *category, const char *name)
  121. {
  122. TraceContext &context = *traceContext;
  123.  
  124. assert(context.scopeTokens.count < context.scopeTokens.max);
  125.  
  126. if(context.scopeTokens.count < context.scopeTokens.max)
  127. context.scopeTokens.data[context.scopeTokens.count] = TraceScopeToken(category, name);
  128.  
  129. return context.scopeTokens.count++;
  130. }
  131.  
  132. inline unsigned TraceGetDepth()
  133. {
  134. TraceContext &context = *traceContext;
  135.  
  136. return context.depth;
  137. }
  138.  
  139. inline void TraceEnter(unsigned token)
  140. {
  141. TraceContext &context = *traceContext;
  142.  
  143. if(context.events.count == context.events.max)
  144. TraceDump();
  145.  
  146. TraceEvent &traceEvent = context.events.data[context.events.count++];
  147.  
  148. traceEvent.isEnter = true;
  149. traceEvent.isLabel = false;
  150. traceEvent.token = token;
  151. traceEvent.ts = NULLCTime::clockMicro();
  152.  
  153. context.depth++;
  154. }
  155.  
  156. inline void TraceLeave()
  157. {
  158. TraceContext &context = *traceContext;
  159.  
  160. if(context.events.count == context.events.max)
  161. TraceDump();
  162.  
  163. TraceEvent &traceEvent = context.events.data[context.events.count++];
  164.  
  165. traceEvent.isEnter = false;
  166. traceEvent.isLabel = false;
  167. traceEvent.token = 0;
  168. traceEvent.ts = NULLCTime::clockMicro();
  169.  
  170. assert(context.depth != 0);
  171. context.depth--;
  172. }
  173.  
  174. inline void TraceLeaveTo(unsigned depth)
  175. {
  176. TraceContext &context = *traceContext;
  177.  
  178. while(context.depth > depth)
  179. TraceLeave();
  180. }
  181.  
  182. inline void TraceLabel(const char *str)
  183. {
  184. TraceContext &context = *traceContext;
  185.  
  186. unsigned count = unsigned(strlen(str)) + 1;
  187.  
  188. if(context.labels.count + count >= context.labels.max || context.events.count == context.events.max)
  189. TraceDump();
  190.  
  191. assert(count < context.labels.max);
  192.  
  193. unsigned token = context.labels.count;
  194.  
  195. memcpy(&context.labels.data[context.labels.count], str, count);
  196. context.labels.count += count;
  197.  
  198. TraceEvent &traceEvent = context.events.data[context.events.count++];
  199.  
  200. traceEvent.isEnter = false;
  201. traceEvent.isLabel = true;
  202. traceEvent.token = token;
  203. traceEvent.ts = 0;
  204. }
  205.  
  206. struct TraceScope
  207. {
  208. TraceScope(unsigned token)
  209. {
  210. TraceEnter(token);
  211. }
  212.  
  213. ~TraceScope()
  214. {
  215. TraceLeave();
  216. }
  217. };
  218.  
  219. inline void TraceDump()
  220. {
  221. TraceContext &context = *traceContext;
  222.  
  223. unsigned currentLabel = 0;
  224.  
  225. for(unsigned i = 0; i < context.events.count; i++)
  226. {
  227. TraceEvent &traceEvent = context.events.data[i];
  228.  
  229. if(traceEvent.isEnter)
  230. {
  231. TraceScopeToken &token = context.scopeTokens.data[traceEvent.token];
  232.  
  233. if(context.openEvent)
  234. {
  235. if(currentLabel != 0)
  236. {
  237. context.output.Printf("}");
  238. currentLabel = 0;
  239. }
  240.  
  241. context.output.Printf("},\n");
  242. }
  243. else if(context.needComma)
  244. {
  245. context.output.Printf(",\n");
  246. context.needComma = false;
  247. }
  248.  
  249. context.openEvent = false;
  250.  
  251. context.outputDepth++;
  252.  
  253. if(context.outputDepth > 32)
  254. continue;
  255.  
  256. context.output.Printf("{\"ph\":\"B\",\"ts\":%d,\"pid\":1,\"tid\":1,\"name\":\"%s\",\"cat\":\"%s\"", traceEvent.ts, token.name, token.category);
  257.  
  258. context.openEvent = true;
  259. }
  260. else if(traceEvent.isLabel)
  261. {
  262. if(context.outputDepth > 32)
  263. continue;
  264.  
  265. if(currentLabel == 0)
  266. context.output.Printf(",\"args\":{");
  267. else
  268. context.output.Printf(",");
  269.  
  270. context.output.Printf("\"label %d\":\"%s\"", currentLabel, &context.labels.data[traceEvent.token]);
  271. currentLabel++;
  272. }
  273. else
  274. {
  275. if(context.openEvent)
  276. {
  277. if(currentLabel != 0)
  278. {
  279. context.output.Printf("}");
  280. currentLabel = 0;
  281. }
  282.  
  283. context.output.Printf("},\n");
  284. }
  285. else if(context.needComma)
  286. {
  287. context.output.Printf(",\n");
  288. context.needComma = false;
  289. }
  290.  
  291. context.openEvent = false;
  292.  
  293. if(context.outputDepth > 32)
  294. {
  295. context.outputDepth--;
  296. continue;
  297. }
  298.  
  299. context.output.Printf("{\"ph\":\"E\",\"ts\":%d,\"pid\":1,\"tid\":1}", traceEvent.ts);
  300.  
  301. context.needComma = true;
  302.  
  303. context.outputDepth--;
  304. }
  305. }
  306.  
  307. if(context.openEvent)
  308. {
  309. if(currentLabel != 0)
  310. {
  311. context.output.Printf("}");
  312. currentLabel = 0;
  313. }
  314.  
  315. context.output.Printf("}");
  316.  
  317. context.needComma = true;
  318. }
  319.  
  320. context.openEvent = false;
  321.  
  322. context.events.count = 0;
  323. context.labels.count = 0;
  324. }
  325. }
  326.  
  327. #define TRACE_SCOPE(category, name) static unsigned token = NULLC::TraceGetToken(category, name); NULLC::TraceScope traceScope(token)
  328. #define TRACE_LABEL(str) NULLC::TraceLabel(str)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement