windows下一個用於效能分析的打點計時C++類
阿新 • • 發佈:2018-12-14
最近在改造公司舊系統程式碼(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(); // 列印所有打點計時花費時間 }