cpu_timer类和auto_cpu_timer类用于精确计时,有elapsed、start、is_stopped等方法。使用跨平台的变量(如下),能够实现纳秒级的时间度量。(精度比较高)。

typedef boost::int_least64_t nanosecond_type;

这个类一般用来记录程序运行了多长时间。它被分解为经过时间,操作系统响应用户请求的时间和用户时间。在elapsed方法中,返回的不再是一个数字,而是一个struct cpu_times,这个结构体中,定义为:

struct cpu_times
{
    nanosecond_type wall;
    nanosecond_type user;
    nanosecond_type system;

    void clear() {wall = user = system = 0LL; }
};

按boost官方文档的说法,wall指的是程序运行的真实时间,user指的是用户CPU时间,system指系统CPU时间。其中,真实时间易受其它程序运行干扰,是不稳定的。如果是衡量算法运行时间,更好的度量是user和system之和。从变量类型可以看出,所以的时间单位均为纳秒(ns)。

类的接口很简单:

void cpu_timer::start() noexcept;            				// 开始一个计时器
void cpu_timer::stop()  noexcept;            				// 结束一个计时器
void cpu_timer::resume() noexcept;           				// 如果已经调用了stop,resume可以继续进行计时 
bool cpu_timer::is_stopped() noexcept;       				// 计时器是否已经停止计时(call stop() ), 
cpu_times cpu_timer::elapsed() noexcept;  					// 如果is_stopped(),那么返回从 计时开始 至 stop()之间的时间间隔;
															// 否则, 返回从 计时开始 至 调用此函数 的时间间隔
std::string format(int places, const string &format)const;
std::string format(int places = default_places) const;
															// 返回 elapsed的字符串形式
															// places代表精度,places = 3, 表示精确到小数点后3位,单位为秒
															// format代表格式化字符串 ,常用的是%w,表示cpu_times.wall

小心resume函数, resume并不是重新开始另一个计时器,而是在stop后继续本次计时;想要开始另一次计时,应该调用start。

默认的输出格式为:

5.713010s wall, 5.709637s user + 0.000000s system = 5.709637s CPU (99.9%)

官方解释:

In other words, this program ran in 5.713010 seconds as would be measured by a clock on the wall, the operating system charged it for 5.709637 seconds of user CPU time and 0 seconds of system CPU time, the total of these two was 5.709637, and that represented 99.9 percent of the wall clock time.

格式可以自定义,默认的格式定义为:

" %ws wall, %us user + %ss system = %ts CPU (%p%)\n"

%w times.wall

%u times.user

%s times.system

%t times.user + times.system

%p The percentage of times.wall represented by times.user + times.system

当auto_cpu_timer定义的时候,可将格式内容传入构造函数,以控制输出格式。

下面来看一个例子:这个例子测试:使用std::move和不使用的效率差异:

#include <boost/timer/timer.hpp>
#include <memory>
#include <vector>
#include <string>
#include <iostream>

using namespace std;
using namespace boost::timer;


vector<string> createVector_98()
{
    vector<string> vec;
    for (int i = 0; i < 10; ++i){
            vec.emplace_back("helloworld");
    }
    return vec;
}

vector<string> createVector_11()
{
    vector<string> vec;
    for (int i = 0; i < 100; ++i){
        vec.emplace_back("helloworld");
    }
    return move(vec);
}

int main()
{
    const int TEST_TIMES = 100;

    vector<string> result;

    cpu_timer timer;
    timer.start();
    for (int i = 0; i < TEST_TIMES; ++i){
        result = createVector_98();
    }
    cout << "no move" << timer.format(6) << endl;

    timer.start(); // don't call resume()
    
    for (int i = 0; i < TEST_TIMES; ++i){
        result = createVector_11();
    }
    cout << "use move" << timer.format(6) << endl;
}

// 结果如下: 
// no move 0.025558s wall, 0.015600s user + 0.000000s system = 0.015600s CPU (61.0%)
// use move 0.019096s wall, 0.031200s user + 0.000000s system = 0.031200s CPU (163.4%)