Created
October 2, 2019 06:56
-
-
Save WheretIB/550717d32cab60d9cb78d256f0fb9a58 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment