Hana
Loading...
Searching...
No Matches
Instrumentor.h
1#pragma once
2
3#include <string>
4#include <chrono>
5#include <algorithm>
6#include <fstream>
7
8#include <thread>
9
10namespace Hana
11{
13 {
14 std::string Name;
15 long long Start, End;
16 size_t ThreadID;
17 };
18
20 {
21 std::string Name;
22 };
23
24 class Instrumentor
25 {
26 public:
27 Instrumentor()
28 : m_CurrentSession(nullptr)
29 , m_ProfileCount(0)
30 {
31 }
32
33 void BeginSession(const std::string& name, const std::string& filepath = "results.json")
34 {
35 m_OutputStream.open(filepath);
36 WriteHeader();
37 m_CurrentSession = new InstrumentationSession { name };
38 }
39
40 void EndSession()
41 {
42 WriteFooter();
43 m_OutputStream.close();
44 delete m_CurrentSession;
45 m_CurrentSession = nullptr;
46 m_ProfileCount = 0;
47 }
48
49 void WriteProfile(const ProfileResult& result)
50 {
51 if (m_ProfileCount++ > 0)
52 m_OutputStream << ",";
53
54 std::string name = result.Name;
55 std::replace(name.begin(), name.end(), '"', '\'');
56
57 m_OutputStream << "{";
58 m_OutputStream << "\"cat\":\"function\",";
59 m_OutputStream << "\"dur\":" << (result.End - result.Start) << ',';
60 m_OutputStream << "\"name\":\"" << name << "\",";
61 m_OutputStream << "\"ph\":\"X\",";
62 m_OutputStream << "\"pid\":0,";
63 m_OutputStream << "\"tid\":" << result.ThreadID << ",";
64 m_OutputStream << "\"ts\":" << result.Start;
65 m_OutputStream << "}";
66
67 m_OutputStream.flush();
68 }
69
70 void WriteHeader()
71 {
72 m_OutputStream << "{\"otherData\": {},\"traceEvents\":[";
73 m_OutputStream.flush();
74 }
75
76 void WriteFooter()
77 {
78 m_OutputStream << "]}";
79 m_OutputStream.flush();
80 }
81
82 static Instrumentor& Get()
83 {
84 static Instrumentor instance;
85 return instance;
86 }
87
88 private:
89 InstrumentationSession* m_CurrentSession;
90 std::ofstream m_OutputStream;
91 int m_ProfileCount;
92 };
93
94 class InstrumentationTimer
95 {
96 public:
97 InstrumentationTimer(const char* name)
98 : m_Name(name)
99 , m_Stopped(false)
100 {
101 m_StartTimepoint = std::chrono::high_resolution_clock::now();
102 }
103
104 ~InstrumentationTimer()
105 {
106 if (!m_Stopped)
107 Stop();
108 }
109
110 void Stop()
111 {
112 auto endTimepoint = std::chrono::high_resolution_clock::now();
113
114 long long start = std::chrono::time_point_cast<std::chrono::microseconds>(m_StartTimepoint).time_since_epoch().count();
115 long long end = std::chrono::time_point_cast<std::chrono::microseconds>(endTimepoint).time_since_epoch().count();
116
117 size_t threadID = std::hash<std::thread::id>{}(std::this_thread::get_id());
118 Instrumentor::Get().WriteProfile({ m_Name, start, end, threadID });
119
120 m_Stopped = true;
121 }
122 private:
123 const char* m_Name;
124 std::chrono::time_point<std::chrono::high_resolution_clock> m_StartTimepoint;
125 bool m_Stopped;
126 };
127}
128
129#define HN_PROFILE 1
130#if HN_PROFILE
131 #define HN_PROFILE_BEGIN_SESSION(name, filepath) ::Hana::Instrumentor::Get().BeginSession(name, filepath)
132 #define HN_PROFILE_END_SESSION() ::Hana::Instrumentor::Get().EndSession()
133 #define HN_PROFILE_SCOPE(name) ::Hana::InstrumentationTimer timer##__LINE__(name);
134 #define HN_PROFILE_FUNCTION() HN_PROFILE_SCOPE(__FUNCSIG__)
135#else
136 #define HN_PROFILE_BEGIN_SESSION(name, filepath)
137 #define HN_PROFILE_END_SESSION()
138 #define HN_PROFILE_SCOPE(name)
139 #define HN_PROFILE_FUNCTION()
140#endif
Definition Instrumentor.h:20
Definition Instrumentor.h:13