Muto 0.0.1
Cross-Platform Application Template
GitHub Repo | Muto Updates | Muto's Author
Loading...
Searching...
No Matches
Instrumentor.h
Go to the documentation of this file.
1
2/// @file Instrumentor.h
3/// @author TheCherno
4/// @author Damon S. Green II
5/// @brief Provides instrumentation and profiling utilities.
6
7//Copyright © TheCherno
8//Modifications Copyright © 2025 Damon S.Green II(nomad_ii_damon)
9//
10//Licensed under the Apache License, Version 2.0 (the "License");
11//you may not use this file except in compliance with the License.
12//You may obtain a copy of the License at
13//
14//[Apache](http://www.apache.org/licenses/LICENSE-2.0)
15
16#pragma once
17
18#include "Core/Log.h"
19
20#include <algorithm>
21#include <chrono>
22#include <fstream>
23#include <iomanip>
24#include <string>
25#include <thread>
26#include <mutex>
27#include <sstream>
28
29namespace Muto {
30
31 using FloatingPointMicroseconds = std::chrono::duration<double, std::micro>;
32
33
35 {
36 std::string Name;
37 long long Start, End;
38 uint32_t ThreadID;
39 };
40
42 {
43 std::string Name;
44 };
45
47 {
48 private:
50 std::ofstream m_OutputStream;
51 std::mutex m_Mutex;
52 public:
54 : m_CurrentSession(nullptr)
55 {
56 }
57
58 void BeginSession(const std::string& name, const std::string& filepath = "results.json")
59 {
60 std::lock_guard lock(m_Mutex);
61 if (m_CurrentSession) {
62 // If there is already a current session, end it and start new one
63 if (Log::GetCoreLogger())
64 {
65 MU_CORE_ERROR("Instrumentor::BeginSession('{0}') when session '{1}' already open.", name, m_CurrentSession->Name);
66 }
68 }
69 m_OutputStream.open(filepath);
70 if (m_OutputStream.is_open()) {
73 }
74 else {
75 if (Log::GetCoreLogger())
76 {
77 MU_CORE_ERROR("Instrumentor could not open results file '{0}'.", filepath);
78 }
79 }
82 }
83
85 {
86 std::lock_guard lock(m_Mutex);
88 }
89
90 void WriteProfile(const ProfileResult& result)
91 {
92 m_OutputStream << ",";
93
94 std::string name = result.Name;
95 std::replace(name.begin(), name.end(), '"', '\'');
96
97 m_OutputStream << "{";
98 m_OutputStream << "\"cat\":\"function\",";
99 m_OutputStream << "\"dur\":" << (result.End - result.Start) << ',';
100 m_OutputStream << "\"name\":\"" << name << "\",";
101 m_OutputStream << "\"ph\":\"X\",";
102 m_OutputStream << "\"pid\":0,";
103 m_OutputStream << "\"tid\":" << result.ThreadID << ",";
104 m_OutputStream << "\"ts\":" << result.Start;
105 m_OutputStream << "}";
106
107 std::lock_guard lock(m_Mutex);
109 {
110 //m_OutputStream << json.str();
111 m_OutputStream.flush();
112 }
113 }
114
116 {
117 m_OutputStream << "{\"otherData\": {},\"traceEvents\":[";
118 m_OutputStream.flush();
119 }
120
122 {
123 m_OutputStream << "]}";
124 m_OutputStream.flush();
125 }
126
128 {
130 {
132 m_OutputStream.close();
133 delete m_CurrentSession;
134 m_CurrentSession = nullptr;
135 }
136 }
137
139 {
140 static Instrumentor instance;
141 return instance;
142 }
143 };
144
146 {
147 public:
148 InstrumentationTimer(const char* name)
149 : m_Name(name), m_Stopped(false)
150 {
151 m_StartTimepoint = std::chrono::high_resolution_clock::now();
152 }
153
155 {
156 if (!m_Stopped)
157 Stop();
158 }
159
160 void Stop()
161 {
162 auto endTimepoint = std::chrono::high_resolution_clock::now();
163
164 long long start = std::chrono::time_point_cast<std::chrono::microseconds>(m_StartTimepoint).time_since_epoch().count();
165 long long end = std::chrono::time_point_cast<std::chrono::microseconds>(endTimepoint).time_since_epoch().count();
166
167 uint32_t threadID = std::hash<std::thread::id>{}(std::this_thread::get_id());
168 Instrumentor::Get().WriteProfile({ m_Name, start, end, threadID });
169
170 m_Stopped = true;
171 }
172 private:
173 const char* m_Name;
176 };
177
178
179}
180
182
183 template <size_t N>
185 {
186 char Data[N];
187 };
188
189 template <size_t N, size_t K>
190 constexpr auto CleanupOutputString(const char(&expr)[N], const char(&remove)[K])
191 {
192 ChangeResult<N> result = {};
193
194 size_t srcIndex = 0;
195 size_t dstIndex = 0;
196 while (srcIndex < N)
197 {
198 size_t matchIndex = 0;
199 while (matchIndex < K - 1 && srcIndex + matchIndex < N - 1 && expr[srcIndex + matchIndex] == remove[matchIndex])
200 matchIndex++;
201 if (matchIndex == K - 1)
202 srcIndex += matchIndex;
203 result.Data[dstIndex++] = expr[srcIndex] == '"' ? '\'' : expr[srcIndex];
204 srcIndex++;
205 }
206 return result;
207 }
208}
209
210
211#define MU_PROFILE 1
212#if MU_PROFILE
213 // Resolve which function signature macro will be used. Note that this only
214 // is resolved when the (pre)compiler starts, so the syntax highlighting
215 // could mark the wrong one in your editor!
216 #if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
217 #define MU_FUNC_SIG __PRETTY_FUNCTION__
218 #elif defined(__DMC__) && (__DMC__ >= 0x810)
219 #define MU_FUNC_SIG __PRETTY_FUNCTION__
220 #elif (defined(__FUNCSIG__) || (_MSC_VER))
221 #define MU_FUNC_SIG __FUNCSIG__
222 #elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
223 #define MU_FUNC_SIG __FUNCTION__
224 #elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
225 #define MU_FUNC_SIG __FUNC__
226 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
227 #define MU_FUNC_SIG __func__
228 #elif defined(__cplusplus) && (__cplusplus >= 201103)
229 #define MU_FUNC_SIG __func__
230 #else
231 #define MU_FUNC_SIG "MU_FUNC_SIG unknown!"
232 #endif
233
234 #define MU_PROFILE_BEGIN_SESSION(name, filepath) ::Muto::Instrumentor::Get().BeginSession(name, filepath)
235 #define MU_PROFILE_END_SESSION() ::Muto::Instrumentor::Get().EndSession()
236 #define MU_PROFILE_SCOPE_LINE2(name, line) constexpr auto fixedName##line = InstrumentorUtils::CleanupOutputString(name, "__cdecl ");
237 ::Muto::InstrumentationTimer timer##line(fixedName##line.Data)
238 #define MU_PROFILE_SCOPE_LINE(name, line) MU_PROFILE_SCOPE_LINE2(name, line)
239 #define MU_PROFILE_SCOPE(name) MU_PROFILE_SCOPE_LINE(name, __LINE__)
240 #define MU_PROFILE_FUNCTION() MU_PROFILE_SCOPE(MU_FUNC_SIG)
241#else
242 #define MU_PROFILE_BEGIN_SESSION(name, filepath)
243 #define MU_PROFILE_END_SESSION()
244 #define MU_PROFILE_FUNCTION()
245 #define MU_PROFILE_SCOPE(name)
246#endif
#define MU_CORE_ASSERT(x,...)
Definition Asserts.h:32
#define BIND_EVENT_FN(x)
Binds the given member function of the Application class as an event handler.
Definition Defines_Macros.h:21
#define MU_PROFILE
Definition Instrumentor.h:211
#define MU_PROFILE_SCOPE(name)
Definition Instrumentor.h:239
#define MU_FUNC_SIG
Definition Instrumentor.h:231
#define MU_PROFILE_SCOPE_LINE2(name, line)
Definition Instrumentor.h:236
#define MU_PROFILE_SCOPE_LINE(name, line)
Definition Instrumentor.h:238
#define MU_PROFILE_FUNCTION()
Definition Instrumentor.h:240
#define MU_CORE_WARN(...)
warn: indicates a potential issue or important event
Definition Log.h:40
#define MU_CORE_ERROR(...)
error: indicates an error that has occurred
Definition Log.h:42
#define MU_CORE_INFO(...)
info: general information about application flow
Definition Log.h:38
The core application class that manages the main loop, window, layers, and event handling.
Definition Application.h:70
void OnEvent(Event &e)
Handles incoming events and dispatches them to the appropriate handlers.
Definition Application.cpp:108
float m_LastFrameTime
Time of the last frame, used for calculating timestep.
Definition Application.h:171
void PushLayer(Layer *layer)
Adds a layer to the application layer stack.
Definition Application.cpp:89
virtual ~Application()
Definition Application.cpp:85
void PushOverlay(Layer *overlay)
Adds an overlay layer to the application layer stack.
Definition Application.cpp:96
bool m_Running
Flag indicating whether the application is running.
Definition Application.h:162
Application(ApplicationSettings settings)
Constructs the Application with the given settings.
Definition Application.cpp:48
std::string ResolvePath(const std::string &Path, PathResolveMode Mode=PathResolveMode::AssetsDirectory) const
Resolves the full path to a resource based on a relative path and the application's settings.
Definition Application.cpp:166
std::string ResolvePath_AssetsDirectory(const std::string &Path) const
Resolves the full path to a resource based on the application's assets directory.
Definition Application.cpp:246
void Close()
Closes the application.
Definition Application.cpp:103
static Application * s_Instance
Definition Application.h:177
std::string ResolvePath_WorkingDirectory(const std::string &Path) const
Resolves the full path to a resource based on the application's working directory.
Definition Application.cpp:194
ImGuiLayer * m_ImGuiLayer
ImGui layer for rendering GUI elements.
Definition Application.h:159
bool m_Minimized
Flag indicating whether the application is minimized.
Definition Application.h:165
Application(const std::string &name="")
Constructs the Application with the given name.
Definition Application.cpp:19
std::string ResolvePath_ProjectDirectory(const std::string &Path) const
Resolves the full path to a resource based on the application's project directory.
Definition Application.cpp:220
bool OnWindowClose(WindowCloseEvent &e)
Event handler for window close events.
Definition Application.cpp:272
bool OnWindowResize(WindowResizeEvent &e)
Event handler for window resize events.
Definition Application.cpp:279
MutoResult InitFileSystem(ApplicationSettings &Settings)
Initializes the file system for the application with the given settings.
Definition Application.cpp:416
MutoResult InitFileSystem()
Initializes the file system for the application.
Definition Application.cpp:295
void Run()
Starts the main application loop.
Definition Application.cpp:125
Stack-based templated event dispatcher.
Definition Event.h:66
EventDispatcher(Event &event)
Construct an EventDispatcher for a specific event.
Definition Event.h:76
Abstract base class for all events.
Definition Event.h:35
bool Handled
Indicates whether the event has been handled.
Definition Event.h:60
Definition ImGuiLayer.h:16
virtual void End()
Definition ImGuiLayer.cpp:111
ImGuiLayer()
Definition ImGuiLayer.cpp:22
virtual void Begin()
Definition ImGuiLayer.cpp:102
Definition Instrumentor.h:146
void Stop()
Definition Instrumentor.h:160
~InstrumentationTimer()
Definition Instrumentor.h:154
const char * m_Name
Definition Instrumentor.h:173
std::chrono::time_point< std::chrono::high_resolution_clock > m_StartTimepoint
Definition Instrumentor.h:174
InstrumentationTimer(const char *name)
Definition Instrumentor.h:148
bool m_Stopped
Definition Instrumentor.h:175
Definition Instrumentor.h:47
std::ofstream m_OutputStream
Definition Instrumentor.h:50
void WriteHeader()
Definition Instrumentor.h:115
static Instrumentor & Get()
Definition Instrumentor.h:138
std::mutex m_Mutex
Definition Instrumentor.h:51
void WriteProfile(const ProfileResult &result)
Definition Instrumentor.h:90
void InternalEndSession()
Definition Instrumentor.h:127
void WriteFooter()
Definition Instrumentor.h:121
void BeginSession(const std::string &name, const std::string &filepath="results.json")
Definition Instrumentor.h:58
void EndSession()
Definition Instrumentor.h:84
InstrumentationSession * m_CurrentSession
Definition Instrumentor.h:49
Instrumentor()
Definition Instrumentor.h:53
Represents a reusable application layer that receives lifecycle callbacks (attach,...
Definition Layer.h:17
virtual void OnAttach()
Called when the layer is attached to the application.
Definition Layer.h:28
A logging utility class for the Vesper engine.
Definition Log.h:17
static std::shared_ptr< spdlog::logger > & GetClientLogger()
Returns the client logger instance.
Definition Log.h:26
static void Init()
Initializes the logging system.
Definition Log.cpp:16
static std::shared_ptr< spdlog::logger > & GetCoreLogger()
Returns the core logger instance.
Definition Log.h:24
static std::shared_ptr< spdlog::logger > s_CoreLogger
Definition Log.h:28
static std::shared_ptr< spdlog::logger > s_ClientLogger
Definition Log.h:29
The main renderer class responsible for managing rendering operations.
Definition Renderer.h:15
static void OnWindowResize(uint32_t width, uint32_t height)
Handles window resize events by resizing the viewport.
Definition Renderer.cpp:24
static void Init()
Initializes the renderer.
Definition Renderer.cpp:16
Represents a time step in seconds.
Definition Timestep.h:11
Event for registering window close.
Definition ApplicationEvent.h:49
Event for registering window resize.
Definition ApplicationEvent.h:16
unsigned int GetWidth() const
Get the new width of the window.
Definition ApplicationEvent.h:27
unsigned int GetHeight() const
Get the new height of the window.
Definition ApplicationEvent.h:29
Definition Instrumentor.h:181
char Data[N]
Definition Instrumentor.h:186
constexpr auto CleanupOutputString(const char(&expr)[N], const char(&remove)[K])
Definition Instrumentor.h:190
Definition Instrumentor.h:185
The main namespace for the Muto engine.
Definition Application.cpp:15
long long Start
Definition Instrumentor.h:37
std::string ProjectDirectory
The project directory of the application.
Definition Application.h:38
uint32_t ThreadID
Definition Instrumentor.h:38
MU_RETURN
Definition Enums.h:6
static std::string NormalizePath(const std::string &path)
Normalizes path separators to forward slashes for cross-platform consistency.
Definition ResourceManager.h:10
static std::string JoinPaths(const std::string &base, const std::string &relative)
Joins two path segments with proper separator handling.
Definition ResourceManager.h:22
static bool IsAbsolutePath(const std::string &path)
Determines whether the given path is an absolute path (Unix-style, Windows-style, or drive-letter).
Definition ResourceManager.h:47
PathResolveMode
Specifies the mode for resolving resource paths in the application.
Definition Application.h:22
std::string Name
Definition Instrumentor.h:43
constexpr Ref< T > CreateRef(Args &&... args)
Creates a Ref (shared_ptr) for the given type and constructor arguments.
Definition Defines_Macros.h:71
std::string WorkingDirectory
The working directory of the application.
Definition Application.h:35
long long End
Definition Instrumentor.h:37
std::string AssetsDirectory
The assets directory of the application.
Definition Application.h:41
std::string Name
Definition Instrumentor.h:36
constexpr Scope< T > CreateScope(Args &&... args)
Creates a Scope (unique_ptr) for the given type and constructor arguments.
Definition Defines_Macros.h:51
Holds configuration settings for the application.
Definition Application.h:30
Definition Instrumentor.h:42
Definition Instrumentor.h:35
Definition MutoResult.h:8
MU_RETURN Return
Definition MutoResult.h:9
std::string ResultMessage
Definition MutoResult.h:10
std::string ReturnError()
Definition MutoResult.h:21
MutoResult(MU_RETURN RETURN, std::string MESSAGE)
Definition MutoResult.h:13
MutoResult()=default
bool IsSuccess()
Definition MutoResult.h:16