1. 程式人生 > >windows下一個用於效能分析的打點計時C++類

windows下一個用於效能分析的打點計時C++類

  最近在改造公司舊系統程式碼(C++),需要查詢某個函式效能底下原因,所以自己寫了一個打點計時類用於效能分析,其中最主要的取時間函式getSysTimeMicros由同事(楊成)提供。

標頭檔案 performanceCounter.h

裡面時間值單位為微秒,如果計時打點超過20000個,請修改標頭檔案中COUNTER_ARRAY_SIZE。

#pragma once
#include <stdint.h>
#define COUNTER_ARRAY_SIZE 20000
class CPerformanceCounter
{
public:
	CPerformanceCounter(const char* pInfo = NULL);
	~CPerformanceCounter();
	void debugAllElapseInfo();
	int64_t getStartTime() const;
	int64_t getAllElapseUSec();
	int getTickMaxElapseIndex();
	int getTickMinElapseIndex();
	int getCount() const;
	int64_t getTickTime(const int index);
	int64_t getTickElapseUSec(const int index);
	bool isStartCount(const int index);
	void start();
	int64_t tick();


	void debugEveryTickElapseInfo();
private:
	static int64_t getSysTimeMicros();
	void debugElapseInfo(const int64_t usedTime, const char* info = NULL);
	int64_t getValidTickElapseUSec(const int index);
	int64_t m_StartTime;
	int64_t m_EndTime;
	int m_Count;
	int64_t m_CounterTimes[COUNTER_ARRAY_SIZE];
	char m_Info[256];
};

實現檔案 performanceCounter.cpp

#include "performanceCounter.h"
#include <stdio.h>
#include <sysinfoapi.h>
#include <debugapi.h>

#define EPOCHFILETIME   (116444736000000000UL)

CPerformanceCounter::CPerformanceCounter(const char* pInfo)
{
	m_StartTime = 0;
	m_EndTime = 0;
	m_Count = 0;
	if (NULL != pInfo) {
		strcpy(m_Info, pInfo);
	}
	else {
		m_Info[0] = 0;
	}
}


CPerformanceCounter::~CPerformanceCounter()
{
}
void CPerformanceCounter::debugAllElapseInfo()
{
	debugElapseInfo(getAllElapseUSec(), "All");
}

void CPerformanceCounter::debugElapseInfo(const int64_t usedTime, const char* info)
{
	int64_t temp = usedTime % 1000000;
	int second = usedTime / 1000000;
	int millise = temp / 1000;
	int micros = temp % 1000;
	char tick_expr[512] = { 0 };
	sprintf(tick_expr, "%s: %s Elpase Time=%ds,%dms,%dus\n", m_Info, NULL == info ? "" : info, second, millise, micros);
	OutputDebugStringA(tick_expr);
}

void CPerformanceCounter::start()
{
	m_Count = 0;
	m_StartTime = getSysTimeMicros();
	m_EndTime = getStartTime();
}

int64_t CPerformanceCounter::tick()
{
	int64_t tmpTime = m_EndTime;
	m_EndTime = getSysTimeMicros();
	m_CounterTimes[m_Count++] = m_EndTime;
	return m_EndTime - tmpTime;
}

void CPerformanceCounter::debugEveryTickElapseInfo()
{
	char info[20];
	for (int i = 0; i < m_Count; i++) {
		sprintf(info, "Tick %d", i + 1);
		debugElapseInfo(getTickElapseUSec(i), info);
	}
}

int64_t CPerformanceCounter::getStartTime() const
{
	return m_StartTime;
}

int64_t CPerformanceCounter::getAllElapseUSec()
{
	return m_EndTime - m_StartTime;
}

int CPerformanceCounter::getTickMaxElapseIndex()
{
	int result = -1;
	int64_t m_MaxTime = 0;
	int64_t tmpTime;
	for (int i = 0; i < m_Count; i++) {
		tmpTime = getTickElapseUSec(i);
		if (tmpTime > m_MaxTime) {
			m_MaxTime = tmpTime;
			result = i;
		}
	}
	return result;
}

int CPerformanceCounter::getTickMinElapseIndex()
{
	int result = -1;
	int64_t m_MinTime = 0x7fffffffffffff;
	int64_t tmpTime;
	for (int i = 0; i < m_Count; i++) {
		tmpTime = getTickElapseUSec(i);
		if (tmpTime < m_MinTime) {
			m_MinTime = tmpTime;
			result = i;
		}
	}
	return result;
}

int CPerformanceCounter::getCount() const
{
	return m_Count;
}

int64_t CPerformanceCounter::getTickTime(const int index)
{
	if (isStartCount(index)) {
		return 0;
	}
	return m_CounterTimes[index];
}

int64_t CPerformanceCounter::getTickElapseUSec(const int index)
{
	if (isStartCount(index)) {
		return -1;
	}
	return getValidTickElapseUSec(index);

}

int64_t CPerformanceCounter::getValidTickElapseUSec(const int index)
{
	return 0 == index ? m_CounterTimes[index] - m_StartTime : m_CounterTimes[index] - m_CounterTimes[index - 1];
}

bool CPerformanceCounter::isStartCount(const int index)
{
	return index < 0 || index > m_Count - 1;
}

int64_t CPerformanceCounter::getSysTimeMicros()
{
	// 從1601年1月1日0:0:0:000到1970年1月1日0:0:0:000的時間(單位100ns)
	FILETIME ft;
	LARGE_INTEGER li;
	GetSystemTimeAsFileTime(&ft);
	li.LowPart = ft.dwLowDateTime;
	li.HighPart = ft.dwHighDateTime;
	// 從1970年1月1日0:0:0:000到現在的微秒數(UTC時間)
	return (li.QuadPart - EPOCHFILETIME) / 10;
}

使用範例:

	CPerformanceCounter performanceCounter("Refresh Original");
	CRefreshRDBYCOriginalImpl refreshRDBYC;
	performanceCounter.start();
	for (int i = 0; i < PERFORMANCE_TEST_RUN_NUM; i++) {
		refreshRDBYC.refresh();
		performanceCounter.tick();
	}
	performanceCounter.debugEveryTickElapseInfo(); // 列印每個打點計時花費時間
	performanceCounter.debugAllElapseInfo(); // 列印所有打點計時花費時間
}