cleanup and instrumentation
This commit is contained in:
138
open_engine/include/open_engine/instrumentor.hpp
Normal file
138
open_engine/include/open_engine/instrumentor.hpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#ifndef INSTRUMENTOR_HPP
|
||||
#define INSTRUMENTOR_HPP
|
||||
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
namespace OpenEngine {
|
||||
struct ProfileResult
|
||||
{
|
||||
std::string name;
|
||||
long long start, end;
|
||||
uint32_t thread_id;
|
||||
};
|
||||
|
||||
struct InstrumentationSession
|
||||
{
|
||||
const char* name;
|
||||
};
|
||||
|
||||
class Instrumentor
|
||||
{
|
||||
public:
|
||||
~Instrumentor()
|
||||
{
|
||||
EndSession();
|
||||
};
|
||||
|
||||
void BeginSession(const char* name, const std::string& filepath = "results.json")
|
||||
{
|
||||
output_stream.open(filepath);
|
||||
WriteHeader();
|
||||
};
|
||||
|
||||
void EndSession()
|
||||
{
|
||||
WriteFooter();
|
||||
output_stream.flush();
|
||||
output_stream.close();
|
||||
profile_count = 0;
|
||||
};
|
||||
|
||||
void WriteProfile(const ProfileResult& result)
|
||||
{
|
||||
if (profile_count++ > 0)
|
||||
output_stream << ",";
|
||||
|
||||
std::string name = result.name;
|
||||
std::replace(name.begin(), name.end(), '"', '\'');
|
||||
|
||||
output_stream << "{";
|
||||
output_stream << "\"cat\":\"function\",";
|
||||
output_stream << "\"dur\":" << (result.end - result.start) << ',';
|
||||
output_stream << "\"name\":\"" << name << "\",";
|
||||
output_stream << "\"ph\":\"X\",";
|
||||
output_stream << "\"pid\":0,";
|
||||
output_stream << "\"tid\":" << result.thread_id << ",";
|
||||
output_stream << "\"ts\":" << result.start;
|
||||
output_stream << "}";
|
||||
};
|
||||
|
||||
void WriteHeader()
|
||||
{
|
||||
output_stream << "{\"otherData\": {},\"traceEvents\":[";
|
||||
};
|
||||
|
||||
void WriteFooter()
|
||||
{
|
||||
output_stream << "]}";
|
||||
};
|
||||
|
||||
static Instrumentor& Get()
|
||||
{
|
||||
static Instrumentor instance;
|
||||
return instance;
|
||||
};
|
||||
|
||||
private:
|
||||
Instrumentor()
|
||||
{
|
||||
};
|
||||
|
||||
private:
|
||||
std::ofstream output_stream;
|
||||
int profile_count = 0;
|
||||
};
|
||||
|
||||
class InstrumentationTimer
|
||||
{
|
||||
public:
|
||||
InstrumentationTimer(const char* name)
|
||||
: name(name), stopped(false)
|
||||
{
|
||||
start_timepoint = std::chrono::high_resolution_clock::now();
|
||||
};
|
||||
|
||||
~InstrumentationTimer()
|
||||
{
|
||||
if (!stopped)
|
||||
Stop();
|
||||
};
|
||||
|
||||
void Stop()
|
||||
{
|
||||
auto end_timepoint = std::chrono::high_resolution_clock::now();
|
||||
|
||||
long long start = std::chrono::time_point_cast<std::chrono::microseconds>(start_timepoint).time_since_epoch().count();
|
||||
long long end = std::chrono::time_point_cast<std::chrono::microseconds>(end_timepoint).time_since_epoch().count();
|
||||
|
||||
uint32_t thread_id = std::hash<std::thread::id>{}(std::this_thread::get_id());
|
||||
Instrumentor::Get().WriteProfile({ name, start, end, thread_id });
|
||||
|
||||
stopped = true;
|
||||
};
|
||||
|
||||
private:
|
||||
const char* name;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> start_timepoint;
|
||||
bool stopped;
|
||||
};
|
||||
}
|
||||
|
||||
#define OE_PROFILE 1
|
||||
#if OE_PROFILE
|
||||
#define OE_PROFILE_BEGIN_SESSION(name, filepath) ::OpenEngine::Instrumentor::Get().BeginSession(name, filepath)
|
||||
#define OE_PROFILE_END_SESSION() ::OpenEngine::Instrumentor::Get().EndSession()
|
||||
#define OE_PROFILE_SCOPE(name) ::OpenEngine::InstrumentationTimer timer##__LINE__(name);
|
||||
#define OE_PROFILE_FUNCTION() OE_PROFILE_SCOPE(__PRETTY_FUNCTION__)
|
||||
#else
|
||||
#define OE_PROFILE_BEGIN_SESSION(name, filepath)
|
||||
#define OE_PROFILE_END_SESSION()
|
||||
#define OE_PROFILE_SCOPE(name)
|
||||
#define OE_PROFILE_FUNCTION()
|
||||
#endif
|
||||
|
||||
#endif // INSTRUMENTOR_HPP
|
||||
Reference in New Issue
Block a user