SHARE
TWEET

Untitled

a guest Oct 20th, 2019 91 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top