It was more as a learning experience tool than anything, I guess you(I/we) can probably buy your way to the knowledge too but I wanted to grab a wrench and start taking things apart instead.
If anyone wanted to humour me, after a little more shuffling, tweaking, renaming, I'm currently here:
"Profiler.h"
#ifndef Profiler_h
#define Profiler_h
#ifndef PROFILE_RESULTS_MAX
#define PROFILE_RESULTS_MAX 100
#endif
struct ProfileResult {
const char* name;
uint32_t startTime, endTime;
};
class Profiler
{
private:
int resultCount;
public:
ProfileResult results[PROFILE_RESULTS_MAX] = {0};
void beginSession() {
Serial.println(F("Profiling..."));
Serial.println();
resultCount = 0;
}
void endSession()
{
printHeader();
printResults();
printFooter();
resultCount = 0;
Serial.println();
Serial.println(F("Profiling Complete"));
}
void saveResult(const ProfileResult& result) {
if (resultCount < PROFILE_RESULTS_MAX)
results[resultCount++] = result;
}
void printResults() {
for (byte i = 0; i < resultCount; i++) {
Serial.println(F("{"));
Serial.println(F("\"cat\":\"function\","));
Serial.print(F("\"dur\":"));
Serial.print(results[i].endTime - results[i].startTime);
Serial.println(F(","));
Serial.print(F("\"name\":\""));
Serial.print(results[i].name);
Serial.println(F("\","));
Serial.println(F("\"ph\":\"X\","));
Serial.println(F("\"pid\":0,"));
Serial.println(F("\"tid\":0,"));
Serial.print(F("\"ts\":"));
Serial.println(results[i].startTime);
if (i < resultCount - 1)
Serial.println(F("},"));
else
Serial.println(F("}"));
}
}
void printHeader() {
Serial.println(F("{\"otherData\": {},\"traceEvents\":["));
}
void printFooter() {
Serial.println(F("]}"));
}
static Profiler& get() {
static Profiler instance;
return instance;
}
};
class ProfileTimer
{
public:
ProfileTimer(const char* name)
: name(name), startTime(micros()) { }
~ProfileTimer() {
Profiler::get().saveResult({name, startTime, micros()});
}
private:
const char* name;
const uint32_t startTime;
};
#if PROFILING
#define STR_INDIR(x) #x
#define STR(x) STR_INDIR(x)
#define PROFILE_BEGIN() Profiler::get().beginSession();
#define PROFILE_FUNCTION() ProfileTimer timer##__LINE__(__PRETTY_FUNCTION__);
#define PROFILE_SCOPE() ProfileTimer timer##__LINE__("Line:" STR(__LINE__));
#define PROFILE_END() Profiler::get().endSession();
#else
#define PROFILE_BEGIN()
#define PROFILE_FUNCTION()
#define PROFILE_SCOPE()
#define PROFILE_END()
#endif
#endif
It should still work with the example code in post #15.
It now stores up the results and prolongs all printing until the very end. So at any given capture point we're only saving the timestamps and const char* to an array.
Can I make this more lightweight / less intrusive on the performance it's intended to profile?