使用chrome tracing 可視化benchmark結果

打開chrome內核的瀏覽器,輸入:chrome://tracing

 

 

將我們benchmark結果的json文件直接拖動到瀏覽器中就可以看到benchmark的結果。效果圖如下:

 

 

C++實現

實現計時器類,並輸出調用函數相關的調用信息到文件中,具體實現如下:

#pragma once
#include <iostream>
#include <fstream>
#include <chrono>
#include <algorithm>
#include <thread>

#define PROFILING 1
#if PROFILING
#define PROFILE_SCOPE(name) InstrumentationTimer timer##__LINE__(name)
#define PROFILE_FUNCTION() PROFILE_SCOPE(__FUNCSIG__)
#else 
#define PROFILE_SCORE(name)
#endif

//當前監測的會話
struct InstrumentationSession
{
	std::string name;
};

//檢測結果數據
struct ProfileResult
{
	std::string name;		//調用棧函數名稱
	long long start, stop;	//起止時間
	uint32_t threadID;		//線程ID
};

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 = "result.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.stop - 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
{
private:
	std::string title;
	std::chrono::high_resolution_clock::time_point m_start;
	bool m_stoped;
public:

	InstrumentationTimer(const std::string& title) : title(title), m_stoped(false)
	{
		m_start = std::chrono::high_resolution_clock::now();
	}

	~InstrumentationTimer()
	{
		if (!m_stoped)
		{
			stop();
		}
	}

	void stop()
	{
		auto m_stop = std::chrono::high_resolution_clock::now();

		long long start = std::chrono::time_point_cast<std::chrono::microseconds>(m_start).time_since_epoch().count();
		long long stop = std::chrono::time_point_cast<std::chrono::microseconds>(m_stop).time_since_epoch().count();
		
		uint32_t threadID = std::hash<std::thread::id>{}(std::this_thread::get_id());
		Instrumentor::Get().WriteProfile({ title, start, stop, threadID});
		m_stoped = true;
	}
};

  測試調用:

#include <iostream>
#include <string>
#include "Timer.h"
#include <cmath>

void Function1()
{
	PROFILE_FUNCTION();
	for (int i = 0; i < 1000; i++)
	{
		std::cout << pow(i, sqrt(sqrt(i))) << " ";
	}
	std::cout << std::endl;
}

void Function2(int v)
{
	PROFILE_FUNCTION();
	for (int i = 0; i < 1000; i++)
	{
		std::cout << abs(i * v) << " ";
	}
	std::cout << std::endl;
}

namespace benchmark {
	void RunApp()
	{
		PROFILE_FUNCTION();
		std::thread a([]() {Function1(); });
		std::thread b([]() {Function2(10); });

		a.join();
		b.join();
	}
}

int main()
{
	Instrumentor::Get().BeginSession("profile");
	benchmark::RunApp();
	Instrumentor::Get().EndSession();

}

  將執行結果的result.json文件拖到瀏覽器內:

 

參考:

https://www.chromium.org/developers/how-tos/trace-event-profiling-tool

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章