C++利用宏实现统计运行时间工具
源自OSRM中的经典代码
背景
OSRM backend 代码中有一个timing_util.hpp的头文件,其利用宏以及c++11 chrono 实现了统计代码运行时间的工具。
在工程中统计代码运行时间非常常用,本文介绍OSRM timing_util的实现原理,并用示例来说明。
实现解析
timing_util.hpp
#ifndef TIMING_UTIL_HPP
#define TIMING_UTIL_HPP
#include <chrono>
#include <cstdint>
namespace osrm
{
namespace util
{
// 用TIMER_START 定义一个变量记录开始的时间
#define TIMER_START(_X) auto _X##_start = std::chrono::steady_clock::now(), _X##_stop = _X##_start
// 用TIMER_STOP 定义一个变量记录结束的时间
#define TIMER_STOP(_X) _X##_stop = std::chrono::steady_clock::now()
// TIMER_NSEC 定义start到stop经历了多少纳秒
#define TIMER_NSEC(_X) \
std::chrono::duration_cast<std::chrono::nanoseconds>(_X##_stop - _X##_start).count()
// TIMER_USEC 定义start到stop历经多少微秒
#define TIMER_USEC(_X) \
std::chrono::duration_cast<std::chrono::microseconds>(_X##_stop - _X##_start).count()
// TIMER_MSEC 定义start到stop经历多少毫秒
#define TIMER_MSEC(_X) \
(0.000001 * \
std::chrono::duration_cast<std::chrono::nanoseconds>(_X##_stop - _X##_start).count())
// TIMER_SEC 定义start到stop经历多少秒
#define TIMER_SEC(_X) \
(0.000001 * \
std::chrono::duration_cast<std::chrono::microseconds>(_X##_stop - _X##_start).count())
// TIMER_MIN 定义start到stop经历多少分钟
#define TIMER_MIN(_X) \
std::chrono::duration_cast<std::chrono::minutes>(_X##_stop - _X##_start).count()
}
}
#endif // TIMING_UTIL_HPP
timing_util在定义宏变量时使用 ##,##的作用是把宏参数和相邻的字符进行字符串连接,# 的作用是把宏参数当做一个字符串。以下是关于宏中# 以及## 用法的示例。
/*************************************************************************
> File Name: test_macro.cpp
> Author: ce39906
> Mail: ce39906@163.com
> Created Time: 2018-06-05 17:38:01
************************************************************************/
#include <iostream>
#define STR(s) #s
#define CONS(a, b) int(a##e##b)
int main()
{
// 输出字符串abc
std::cout << STR(abc) << std::endl;
// 输出2000 (2e3 == 2000)
std::cout << CONS(2, 3) << std::endl;
return 0;
}
TIMING_UTIL统计运行时间示例
timing_util.cpp
/*************************************************************************
> File Name: timing_util.cpp
> Author: ce39906
> Mail: ce39906@163.com
> Created Time: 2018-06-05 17:46:50
************************************************************************/
#include "timing_util.hpp"
#include <iostream>
using namespace osrm::util;
int main()
{
TIMER_START(x);
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
int ij = i * j;
}
}
TIMER_STOP(x);
std::cout << "Two Level Loop Cost " << TIMER_NSEC(x) << " ns.\n";
std::cout << "Two Level Loop Cost " << TIMER_USEC(x) << " us.\n";
std::cout << "Two Level Loop Cost " << TIMER_MSEC(x) << " ms.\n";
std::cout << "Two Level Loop Cost " << TIMER_SEC(x) << " s.\n";
std::cout << "Two Level Loop Cost " << TIMER_MIN(x) << " min.\n";
return 0;
}
编译
g++ timing_util.cpp -o timing_util --std=c++11
运行
./timing_util
运行结果如下