Skip to content

Instantly share code, notes, and snippets.

@Lecrapouille
Last active December 30, 2019 10:14
Show Gist options
  • Save Lecrapouille/1341f9392fb79831efe5ff7f42374c54 to your computer and use it in GitHub Desktop.
Save Lecrapouille/1341f9392fb79831efe5ff7f42374c54 to your computer and use it in GitHub Desktop.
Modified version of TheCherno's Instrumentor.h
// 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