通用型C/C++程序性能测试Benchmark的简单实现

时间:2022-09-14 12:25:54

     在完成一个算法的改进后, 除了人工估算时间复杂度外, 我们可能还希望直观地检测改进效果, 现有的性能分析工具比如Intel® VTune™ Amplifier自然满足需求, 然而有时候使用第三方工具的成本却可能超出我们的所需(也许我们仅仅需要大概地对比便能得到结果), 或者我们希望能在代码中控制测试流程, 这时写一个Benchmark便是首选了.

     本文实现了一个简单的通用型Benchmark框架, 因为简单, 它所能得到的信息也十分有限, 不过这已经足够了.(如果你需要更为强健的framework, 推荐使用Celero, C++ Benchmark Authoring Library/Framework)

 

//compiled with /UNICODE
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <RLib_Import.h>

#if _DEBUG
#pragma comment(lib, "RLib_d.lib")
#else
#pragma comment(lib, "RLib.lib")
#endif // _DEBUG

using namespace System;

//-------------------------------------------------------------------------

static Timer timer; //Timer是对高精度计时API QueryPerformanceCounter 的简单封装

//-------------------------------------------------------------------------

static void show_benchmark_result(double interval, const String &prefix = Nothing)
{
GlobalizeString u_prefix(prefix + _T("运行耗时:") + String().Format(_T("%f"),
interval * 1000) + _T("ms") RLIB_NEWLINE);
printf(u_prefix.toGBK());
}

//-------------------------------------------------------------------------

#define SAMPLE_COUNT 1024 //采样次数
void test1()
{
}

//-------------------------------------------------------------------------

void test_wrapper(RLIB_TYPE(test1) *test_t, const String &test_name)
{
printf(RLIB_NEWLINEA);

double intervals[SAMPLE_COUNT];
for (int i = 0; i < RLIB_COUNTOF(intervals); ++i) {
timer.BeginTimer();
test_t();
timer.EndTimer();
intervals[i] = timer.GetDoubleTimeSpan();

//show_benchmark_result(intervals[i]);
} //for

double imin = intervals[0], imax = intervals[0];
for (int i = 1; i < RLIB_COUNTOF(intervals); ++i) {
intervals[0] += intervals[i];
imax = max(imax, intervals[i]);
imin = min(imin, intervals[i]);
}
show_benchmark_result(imin, _T("最小"));
show_benchmark_result(imax, _T("最大"));
show_benchmark_result((intervals[0] - imax - imin) / (RLIB_COUNTOF(intervals) - 2),
test_name + _T(" 平均"));
}

//-------------------------------------------------------------------------

int _tmain(int argc, _TCHAR* argv[])
{
test_wrapper(test1, _T("测试例名"));
printf(RLIB_NEWLINEA);
system("pause");
return argc;
}


此外, 如果调用API不是很方便, 还可以借助rdtsc指令获取大概的CPU时钟周期进行估计.