#include <iostream>
#include <string>
#include <chrono>
#include <cmath>
#include <algorithm>
#include <fstream>
#include <thread>
// how to measure performance visually.
// chrome://tracing-> it loads in a json file and you'll see.
struct ProfileResult
{
std::string Name;
long long Start, End;
uint32_t ThreadID;
};
struct InstrumentationSession
{
std::string Name;
};
// Formatting a json file and write it out into a file.
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 = "testFile/VisualBenchmarkingResults.json")
{
m_OutputStream.open(filepath);
WriteHeader();
m_CurrentSession = new InstrumentationSession{ name };
}
void EndSession(void)
{
WriteFooter();
m_OutputStream.close();
delete m_CurrentSession;
m_CurrentSession = nullptr;
m_ProfileCount = 0;
}
// it's the meat of this entire class.
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 << "\"duration\":" << (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(void)
{
m_OutputStream << "{\"otherData\": {},\"traceEvents\":[";
m_OutputStream.flush();
}
void WriteFooter(void)
{
m_OutputStream << "]}";
m_OutputStream.flush();
}
static Instrumentor& Get(void)
{
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(void)
{
if (!m_Stopped)
{
Stop();
}
}
void Stop(void)
{
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();
auto end = std::chrono::time_point_cast<std::chrono::microseconds>(endTimepoint).time_since_epoch().count();
//std::cout << m_Name << ": " << (end - start) << " us\n";
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;
};
#define PROFILING 1
#if PROFILING
#define PROFILE_SCOPE(name) InstrumentationTimer timer##__LINE__(name)
#define PROFILE_FUNCTION() PROFILE_SCOPE(__FUNCSIG__)
#else
#define PROFILE_SCOPE(name)
#endif
namespace Benchmark {
void PrintFunction(int value)
{
PROFILE_FUNCTION();
for (int i = 0; i < 1000; i++)
{
std::cout << "Hello World #" << i + value << std::endl;
}
}
void PrintFunction(void)
{
PROFILE_FUNCTION();
for (int i = 0; i < 1000; i++)
{
std::cout << "Hello World #" << sqrt(i) << std::endl;
}
}
void RunBenchmarks(void)
{
PROFILE_FUNCTION();
std::cout << "Running Benchmarks...\n";
PrintFunction(2);
std::thread a([]() {PrintFunction(); });
a.join();
}
}
int main(void)
{
Instrumentor::Get().BeginSession("Profile");
Benchmark::RunBenchmarks();
Instrumentor::Get().EndSession();
std::cin.get();
}
【Cherno的C++视频】Visual benchmarking in C++
于 2022-08-16 19:31:02 首次发布