Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instrumentation fixes for #176 and #181 #179

Merged
merged 12 commits into from
Jan 12, 2020
Merged
89 changes: 59 additions & 30 deletions Hazel/src/Hazel/Debug/Instrumentor.h
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ namespace Hazel {
{
std::string Name;
long long Start, End;
uint32_t ThreadID;
std::thread::id ThreadID;
};

struct InstrumentationSession
@@ -23,6 +23,7 @@ namespace Hazel {
class Instrumentor
{
private:
std::mutex m_Mutex;
InstrumentationSession* m_CurrentSession;
std::ofstream m_OutputStream;
int m_ProfileCount;
@@ -34,41 +35,63 @@ namespace Hazel {

void BeginSession(const std::string& name, const std::string& filepath = "results.json")
{
std::lock_guard lock(m_Mutex);
if (m_CurrentSession) {
// If there is already a current session, then close it before beginning new one.
// Subsequent profiling output meant for the original session will end up in the
// newly opened session instead. That's better than having badly formatted
// profiling output.
if (Log::GetCoreLogger()) { // Edge case: BeginSession() might be before Log::Init()
HZ_CORE_ERROR("Instrumentor::BeginSession('{0}') when session '{1}' already open.", name, m_CurrentSession->Name);
}
InternalEndSession();
}
m_OutputStream.open(filepath);
WriteHeader();
m_CurrentSession = new InstrumentationSession{ name };
if (m_OutputStream.is_open()) {
m_CurrentSession = new InstrumentationSession({name});
WriteHeader();
} else {
HZ_CORE_ERROR("Instrumentor could not open results file '{0}'.", filepath);
}
}

void EndSession()
{
WriteFooter();
m_OutputStream.close();
delete m_CurrentSession;
m_CurrentSession = nullptr;
m_ProfileCount = 0;
std::lock_guard lock(m_Mutex);
InternalEndSession();
}

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 << "}";
std::lock_guard lock(m_Mutex);
if (m_CurrentSession) {
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();
}
}

m_OutputStream.flush();
static Instrumentor& Get() {
static Instrumentor instance;
return instance;
}

private:

void WriteHeader()
{
m_OutputStream << "{\"otherData\": {},\"traceEvents\":[";
@@ -81,11 +104,18 @@ namespace Hazel {
m_OutputStream.flush();
}

static Instrumentor& Get()
{
static Instrumentor instance;
return instance;
// Note: you must already own lock on m_Mutex before
// calling InternalEndSession()
void InternalEndSession() {
if (m_CurrentSession) {
WriteFooter();
m_OutputStream.close();
delete m_CurrentSession;
m_CurrentSession = nullptr;
m_ProfileCount = 0;
}
}

};

class InstrumentationTimer
@@ -110,8 +140,7 @@ namespace Hazel {
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 });
Instrumentor::Get().WriteProfile({ m_Name, start, end, std::this_thread::get_id()});

m_Stopped = true;
}
1 change: 0 additions & 1 deletion Sandbox/HazelProfile-Runtime.json

This file was deleted.

1 change: 0 additions & 1 deletion Sandbox/HazelProfile-Shutdown.json

This file was deleted.

1 change: 0 additions & 1 deletion Sandbox/HazelProfile-Startup.json

This file was deleted.