使用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

 

posted @ 2020-11-22 18:38  xnuwu  阅读(3797)  评论(0编辑  收藏  举报