Last active
October 17, 2025 07:36
-
Star
(235)
You must be signed in to star a gist -
Fork
(60)
You must be signed in to fork a gist
-
-
Save TheCherno/31f135eea6ee729ab5f26a6908eb3a5e to your computer and use it in GitHub Desktop.
Revisions
-
TheCherno revised this gist
Nov 20, 2019 . 1 changed file with 6 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -3,12 +3,12 @@ // Usage: include this header file somewhere in your code (eg. precompiled header), and then use like: // // Instrumentor::Get().BeginSession("Session Name"); // Begin session // { // InstrumentationTimer timer("Profiled Scope Name"); // Place code like this in scopes you'd like to include in profiling // // Code // } // Instrumentor::Get().EndSession(); // End Session // // You will probably want to macro-fy this, to switch on/off easily and use things like __FUNCSIG__ for the profile name. // @@ -96,8 +96,8 @@ class Instrumentor static Instrumentor& Get() { static Instrumentor instance; return instance; } }; @@ -130,6 +130,6 @@ class InstrumentationTimer } private: const char* m_Name; std::chrono::time_point<std::chrono::high_resolution_clock> m_StartTimepoint; bool m_Stopped; }; -
TheCherno created this gist
Nov 16, 2019 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,135 @@ // // Basic instrumentation profiler by Cherno // Usage: include this header file somewhere in your code (eg. precompiled header), and then use like: // // Instrumentor::Get().BeginSession("Session Name"); // Begin session // { // InstrumentationTimer timer("Profiled Scope Name"); // Place code like this in scopes you'd like to include in profiling // // Code // } // Instrumentor::Get().EndSession(); // End Session // // You will probably want to macro-fy this, to switch on/off easily and use things like __FUNCSIG__ for the profile name. // #pragma once #include <string> #include <chrono> #include <algorithm> #include <fstream> #include <thread> struct ProfileResult { std::string Name; long long Start, End; uint32_t ThreadID; }; struct InstrumentationSession { std::string Name; }; class Instrumentor { private: InstrumentationSession* m_CurrentSession; std::ofstream m_OutputStream; int m_ProfileCount; public: Instrumentor() : m_CurrentSession(nullptr), m_ProfileCount(0) { } void BeginSession(const std::string& name, const std::string& filepath = "results.json") { m_OutputStream.open(filepath); WriteHeader(); m_CurrentSession = new InstrumentationSession{ name }; } void EndSession() { WriteFooter(); m_OutputStream.close(); delete m_CurrentSession; m_CurrentSession = nullptr; m_ProfileCount = 0; } void WriteProfile(const ProfileResult& result) { if (m_ProfileCount++ > 0) m_OutputStream << ","; std::string name = result.Name; std::replace(name.begin(), name.end(), '"', '\''); m_OutputStream << "{"; m_OutputStream << "\"cat\":\"function\","; m_OutputStream << "\"dur\":" << (result.End - result.Start) << ','; m_OutputStream << "\"name\":\"" << name << "\","; m_OutputStream << "\"ph\":\"X\","; m_OutputStream << "\"pid\":0,"; m_OutputStream << "\"tid\":" << result.ThreadID << ","; m_OutputStream << "\"ts\":" << result.Start; m_OutputStream << "}"; m_OutputStream.flush(); } void WriteHeader() { m_OutputStream << "{\"otherData\": {},\"traceEvents\":["; m_OutputStream.flush(); } void WriteFooter() { m_OutputStream << "]}"; m_OutputStream.flush(); } static Instrumentor& Get() { static Instrumentor* instance = new Instrumentor(); return *instance; } }; class InstrumentationTimer { public: InstrumentationTimer(const char* name) : m_Name(name), m_Stopped(false) { m_StartTimepoint = std::chrono::high_resolution_clock::now(); } ~InstrumentationTimer() { if (!m_Stopped) Stop(); } void Stop() { auto endTimepoint = std::chrono::high_resolution_clock::now(); long long start = std::chrono::time_point_cast<std::chrono::microseconds>(m_StartTimepoint).time_since_epoch().count(); long long end = std::chrono::time_point_cast<std::chrono::microseconds>(endTimepoint).time_since_epoch().count(); uint32_t threadID = std::hash<std::thread::id>{}(std::this_thread::get_id()); Instrumentor::Get().WriteProfile({ m_Name, start, end, threadID }); m_Stopped = true; } private: const char* m_Name; std::chrono::time_point<std::chrono::steady_clock> m_StartTimepoint; bool m_Stopped; };