Last active
December 30, 2019 10:14
-
-
Save Lecrapouille/1341f9392fb79831efe5ff7f42374c54 to your computer and use it in GitHub Desktop.
Modified version of TheCherno's Instrumentor.h
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
// This file is a modified version of: | |
// https://github.com/TheCherno/Hazel | |
// Hazel/master/Hazel/src/Hazel/Debug/Instrumentor.h | |
// Copyright TheCherno. License Apache-2.0 | |
// For more details see: | |
// https://www.youtube.com/watch?v=xlAH4dbMVnU | |
#pragma once | |
#include <algorithm> | |
#include <chrono> | |
#include <fstream> | |
#include <iomanip> | |
#include <string> | |
#include <thread> | |
namespace Hazel { | |
class Instrumentor | |
{ | |
private: | |
std::string m_CurrentSession; | |
std::ofstream m_OutputStream; | |
bool m_Started; | |
public: | |
static Instrumentor& Get() | |
{ | |
static Instrumentor instance; | |
return instance; | |
} | |
void BeginSession(const char* name, const char* filepath = "results.json") | |
{ | |
m_Started = true; | |
m_OutputStream.open(filepath); | |
m_OutputStream << std::setprecision(3) << std::fixed; | |
WriteHeader(); | |
m_CurrentSession = name; | |
} | |
void EndSession() | |
{ | |
if (!m_Started) | |
return ; | |
WriteFooter(); | |
m_Started = false; | |
} | |
void WriteProfile(const char* name, double const start, double const end, size_t const threadID) | |
{ | |
if (!m_Started) | |
return ; | |
// Is this really needed ? Can we avoid passing to a string ? | |
std::string funcName(name); | |
std::replace(funcName.begin(), funcName.end(), '"', '\''); | |
// | |
m_OutputStream << "{"; | |
m_OutputStream << "\"cat\":\"function\","; | |
m_OutputStream << "\"dur\":" << (end - start) << ','; | |
m_OutputStream << "\"name\":\"" << funcName << "\","; | |
m_OutputStream << "\"ph\":\"X\","; | |
m_OutputStream << "\"pid\":0,"; | |
m_OutputStream << "\"tid\":" << threadID << ","; | |
m_OutputStream << "\"ts\":" << start; | |
m_OutputStream << "}," << std::endl; | |
} | |
private: | |
void WriteHeader() | |
{ | |
m_OutputStream << "{\"otherData\": {},\"traceEvents\":[" << std::endl; | |
} | |
void WriteFooter() | |
{ | |
m_OutputStream << "{} ]}" << std::endl; | |
} | |
Instrumentor() | |
: m_Started(false) | |
{ | |
} | |
}; | |
class InstrumentationTimer | |
{ | |
using Clock = std::chrono::steady_clock; | |
using TimePoint = std::chrono::time_point<Clock>; | |
public: | |
InstrumentationTimer(const char* name) | |
: m_Name(name), m_Stopped(false) | |
{ | |
m_StartTimepoint = Clock::now(); | |
} | |
~InstrumentationTimer() | |
{ | |
Stop(); | |
} | |
void Stop() | |
{ | |
if (m_Stopped) | |
return ; | |
using namespace std::chrono; | |
Instrumentor::Get().WriteProfile( | |
m_Name, | |
static_cast<double>(time_point_cast<nanoseconds>(m_StartTimepoint).time_since_epoch().count()) / 1000.0, | |
static_cast<double>(time_point_cast<nanoseconds>(Clock::now()).time_since_epoch().count()) / 1000.0, | |
std::hash<std::thread::id>{}(std::this_thread::get_id()) | |
); | |
} | |
private: | |
const char* m_Name; | |
TimePoint m_StartTimepoint; | |
bool m_Stopped; | |
}; | |
} | |
#define HZ_PROFILE 1 | |
#if HZ_PROFILE | |
// Resolve which function signature macro will be used. Note that this only | |
// is resolved when the (pre)compiler starts, so the syntax highlighting | |
// could mark the wrong one in your editor! | |
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__) | |
#define HZ_FUNC_SIG __PRETTY_FUNCTION__ | |
#elif defined(__DMC__) && (__DMC__ >= 0x810) | |
#define HZ_FUNC_SIG __PRETTY_FUNCTION__ | |
#elif defined(__FUNCSIG__) | |
#define HZ_FUNC_SIG __FUNCSIG__ | |
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500)) | |
#define HZ_FUNC_SIG __FUNCTION__ | |
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) | |
#define HZ_FUNC_SIG __FUNC__ | |
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) | |
#define HZ_FUNC_SIG __func__ | |
#elif defined(__cplusplus) && (__cplusplus >= 201103) | |
#define HZ_FUNC_SIG __func__ | |
#else | |
#define HZ_FUNC_SIG "HZ_FUNC_SIG unknown!" | |
#endif | |
#define HZ_PROFILE_BEGIN_SESSION(name, filepath) ::Hazel::Instrumentor::Get().BeginSession(name, filepath) | |
#define HZ_PROFILE_END_SESSION() ::Hazel::Instrumentor::Get().EndSession() | |
#define HZ_PROFILE_SCOPE(name) ::Hazel::InstrumentationTimer timer##__LINE__(name); | |
#define HZ_PROFILE_FUNCTION() HZ_PROFILE_SCOPE(HZ_FUNC_SIG) | |
#else | |
#define HZ_PROFILE_BEGIN_SESSION(name, filepath) | |
#define HZ_PROFILE_END_SESSION() | |
#define HZ_PROFILE_SCOPE(name) | |
#define HZ_PROFILE_FUNCTION() | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment