Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <assert.h>
- #include "Output.h"
- namespace NULLCTime
- {
- void clockMicroInit();
- unsigned clockMicro();
- }
- namespace NULLC
- {
- template<typename T>
- struct TraceArray
- {
- TraceArray(unsigned size)
- {
- count = 0;
- max = size;
- data = new T[size];
- }
- ~TraceArray()
- {
- delete[] data;
- }
- unsigned count;
- unsigned max;
- T *data;
- };
- struct TraceScopeToken
- {
- TraceScopeToken()
- {
- category = "";
- name = "";
- }
- TraceScopeToken(const char *category, const char *name) : category(category), name(name)
- {
- }
- const char *category;
- const char *name;
- };
- struct TraceEvent
- {
- unsigned isEnter : 1;
- unsigned isLabel : 1;
- unsigned token : 30;
- unsigned ts;
- };
- void TraceDump();
- struct TraceContext
- {
- TraceContext(): scopeTokens(4096), labels(262144), events(262144), outputBuf(32768), tempBuf(1024)
- {
- output.stream = output.openStream("trace.json");
- output.outputBuf = outputBuf.data;
- output.outputBufSize = outputBuf.max;
- output.tempBuf = tempBuf.data;
- output.tempBufSize = tempBuf.max;
- output.Print('[');
- needComma = false;
- openEvent = false;
- depth = 0;
- outputDepth = 0;
- }
- ~TraceContext()
- {
- TraceDump();
- output.Print(']');
- output.Flush();
- output.closeStream(output.stream);
- output.stream = NULL;
- }
- OutputContext output;
- bool needComma;
- bool openEvent;
- unsigned depth;
- unsigned outputDepth;
- TraceArray<TraceScopeToken> scopeTokens;
- TraceArray<char> labels;
- TraceArray<TraceEvent> events;
- TraceArray<char> outputBuf;
- TraceArray<char> tempBuf;
- };
- extern TraceContext *traceContext;
- inline TraceContext* TraceGetContext()
- {
- static TraceContext context;
- NULLCTime::clockMicroInit();
- return &context;
- }
- inline unsigned TraceGetToken(const char *category, const char *name)
- {
- TraceContext &context = *traceContext;
- assert(context.scopeTokens.count < context.scopeTokens.max);
- if(context.scopeTokens.count < context.scopeTokens.max)
- context.scopeTokens.data[context.scopeTokens.count] = TraceScopeToken(category, name);
- return context.scopeTokens.count++;
- }
- inline unsigned TraceGetDepth()
- {
- TraceContext &context = *traceContext;
- return context.depth;
- }
- inline void TraceEnter(unsigned token)
- {
- TraceContext &context = *traceContext;
- if(context.events.count == context.events.max)
- TraceDump();
- TraceEvent &traceEvent = context.events.data[context.events.count++];
- traceEvent.isEnter = true;
- traceEvent.isLabel = false;
- traceEvent.token = token;
- traceEvent.ts = NULLCTime::clockMicro();
- context.depth++;
- }
- inline void TraceLeave()
- {
- TraceContext &context = *traceContext;
- if(context.events.count == context.events.max)
- TraceDump();
- TraceEvent &traceEvent = context.events.data[context.events.count++];
- traceEvent.isEnter = false;
- traceEvent.isLabel = false;
- traceEvent.token = 0;
- traceEvent.ts = NULLCTime::clockMicro();
- assert(context.depth != 0);
- context.depth--;
- }
- inline void TraceLeaveTo(unsigned depth)
- {
- TraceContext &context = *traceContext;
- while(context.depth > depth)
- TraceLeave();
- }
- inline void TraceLabel(const char *str)
- {
- TraceContext &context = *traceContext;
- unsigned count = unsigned(strlen(str)) + 1;
- if(context.labels.count + count >= context.labels.max || context.events.count == context.events.max)
- TraceDump();
- assert(count < context.labels.max);
- unsigned token = context.labels.count;
- memcpy(&context.labels.data[context.labels.count], str, count);
- context.labels.count += count;
- TraceEvent &traceEvent = context.events.data[context.events.count++];
- traceEvent.isEnter = false;
- traceEvent.isLabel = true;
- traceEvent.token = token;
- traceEvent.ts = 0;
- }
- struct TraceScope
- {
- TraceScope(unsigned token)
- {
- TraceEnter(token);
- }
- ~TraceScope()
- {
- TraceLeave();
- }
- };
- inline void TraceDump()
- {
- TraceContext &context = *traceContext;
- unsigned currentLabel = 0;
- for(unsigned i = 0; i < context.events.count; i++)
- {
- TraceEvent &traceEvent = context.events.data[i];
- if(traceEvent.isEnter)
- {
- TraceScopeToken &token = context.scopeTokens.data[traceEvent.token];
- if(context.openEvent)
- {
- if(currentLabel != 0)
- {
- context.output.Printf("}");
- currentLabel = 0;
- }
- context.output.Printf("},\n");
- }
- else if(context.needComma)
- {
- context.output.Printf(",\n");
- context.needComma = false;
- }
- context.openEvent = false;
- context.outputDepth++;
- if(context.outputDepth > 32)
- continue;
- context.output.Printf("{\"ph\":\"B\",\"ts\":%d,\"pid\":1,\"tid\":1,\"name\":\"%s\",\"cat\":\"%s\"", traceEvent.ts, token.name, token.category);
- context.openEvent = true;
- }
- else if(traceEvent.isLabel)
- {
- if(context.outputDepth > 32)
- continue;
- if(currentLabel == 0)
- context.output.Printf(",\"args\":{");
- else
- context.output.Printf(",");
- context.output.Printf("\"label %d\":\"%s\"", currentLabel, &context.labels.data[traceEvent.token]);
- currentLabel++;
- }
- else
- {
- if(context.openEvent)
- {
- if(currentLabel != 0)
- {
- context.output.Printf("}");
- currentLabel = 0;
- }
- context.output.Printf("},\n");
- }
- else if(context.needComma)
- {
- context.output.Printf(",\n");
- context.needComma = false;
- }
- context.openEvent = false;
- if(context.outputDepth > 32)
- {
- context.outputDepth--;
- continue;
- }
- context.output.Printf("{\"ph\":\"E\",\"ts\":%d,\"pid\":1,\"tid\":1}", traceEvent.ts);
- context.needComma = true;
- context.outputDepth--;
- }
- }
- if(context.openEvent)
- {
- if(currentLabel != 0)
- {
- context.output.Printf("}");
- currentLabel = 0;
- }
- context.output.Printf("}");
- context.needComma = true;
- }
- context.openEvent = false;
- context.events.count = 0;
- context.labels.count = 0;
- }
- }
- #define TRACE_SCOPE(category, name) static unsigned token = NULLC::TraceGetToken(category, name); NULLC::TraceScope traceScope(token)
- #define TRACE_LABEL(str) NULLC::TraceLabel(str)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement