程序开发者都会面临一个共同的问题,即写出高质量的代码完成特定的功能。评价代码质量的一个重要标准就是算法的执行效率,也就是算法的执行时间。为了可靠的提高程序的执行效率,首先要知道执行程序所消耗的时间,然后找出可行的方案对程序进行优化。

Timer是Boost中的一个很小的时间库,提供时间度量和进度显示功能,其中包含三个组件:计时器类timer、timer类的子类progress_timer类和进度指示类progress_display。

timer

timer位于boost命名空间中,使用之前需要包含头文件

timer中有3个函数,分别为:

  • elapsed_max(),返回可度量的最大时间间隔
  • elapsed_min(),返回可度量的最小时间间隔
  • elapsed(),返回timer类创建到elapsed()函数调用时所流逝的时间

timer变量声明之后即开始计时工作,之后可以调用 elapsed() 方法来测量对象自创建之后所流逝的时间。成员函数 elapsed_max() 和 elapsed_min() 方法返回 timer 能够测量的时间最大值和最小值,输出单位秒,精确度为毫秒。

// boost::timer库, 用于性能测试等需要计时的任务。   
// boost::timer不适合高精度的时间测量任务。 它的精度依赖于操作系统或编译器,难以做到跨平台。   
// boost::timer也不适合大跨度时间段的测量,可提供的最大跨度只有几百个小时,如果需要以天、月甚至年作为时间的单位则不能使用timer。 应该使用 date_time库。  
void test_timer()  
{  
    // 声明一个计时器对象,并开始计时!  
    boost::timer t;  
  
    long long sum = 0;  
    for (int i = 0; i < 1000000 ; i++)  
        sum = sum + i;  
  
    // 计算时间差, 测量自对象创建后所流逝的时间。  
    double dl = t.elapsed();  
    std::cout << "now time elapsed:" << dl << std::endl;  
  
    //可度量的最大时间,以秒为单位      
    std::cout << "max timespan:" << t.elapsed_max() /3600 << "h" << std::endl;  
    //可度量的最小时间,以秒为单位  
    std::cout << "min timespan:" << t.elapsed_min() << "s" << std::endl;  
  
    // 还有一个restart()开始重新计时  
    t.restart();  
}  

timer使用C语言中头文件的std::clock()函数:返回自进程启动后经过的时钟数(clock()),而每秒的时钟频率位宏定义的常量:CLOCKS_PER_SEC,那么我们使用(end_clock - start_clock) / CLOCKS_PER_SEC 得到经过的时间。

progress_timer类

progress_timer类是timer类的子类,此类具有一定的特殊性,在系统对此类对象进行析构时会自动调用此类的elapsed()函数,输出系统执行程序所消耗的时间。

progress_timer 精度问题,只能保留到小数点后两位,精确到百分之一秒。

// boost::progress_timer也是一个计时器,它继承自timer,  
// 它会在析构时自动输出时间,省去了boost::timer手动调用elapsed()的工作,是一个用于自动计时相当方便的小工具。  
void test_progress_timer()  
{  
    boost::progress_timer pt;  
  
    long long sum = 0;  
    for (int i = 0; i < 10000000 ; i++)  
        sum = sum + i;  
  
    pt.elapsed();  
  
    // 另外一种方法,不要用el 
    // 可以使用花括号,来使 progress_timer 实现计时功能。 
    {  
        boost::progress_timer pt;  
        // do_something();  
    }   // pt析构时自动输出流逝时间  
}  

progress_display类

progress_display类用于显示程序的执行进度,使得用户获得动态感,使用前需要包含头文件。在构造函数中传入总数,然后迭代更新进度条。

progress_display 向标准输出 cout 输出字符,无法将进度条和输出分离,如果循环中带有输出,则显示会很难看。

void test_progress_display()  
{  
    std::vector<std::string> v(1000000, "abcdefg");  
    std::ofstream fs("d:\\test.txt");  
  
    // 声明一个progress_display 对象,基数是v的大小  
    boost::progress_display pd(v.size());  
  
    // 开始选代遍历向量,处理字符串  
    std::vector<std::string>::iterator pos;  
    for (pos = v.begin(); pos != v.end(); ++pos)  
    {  
        fs << *pos << std::endl;  
        ++pd; // 更新进度显示  
    }  
}  
  
// 进度表在打印过程中出错的处理  
void test_progress_display_restart()  
{  
    std::vector<std::string> v(100 , "abcd");  
    v[10] = "";  
    v[23] = "";  
    std::ofstream fs("d:\\test.txt");  
    boost::progress_display pd(v.size());  
    std::vector<std::string>::iterator pos;  
    for (pos = v.begin(); pos != v.end(); ++pos)  
    {  
        fs << *pos << std::endl;  
        ++pd;  
        if (pos->empty())  
        {  
            std::cout << std::endl;  
            std::cout << "Error: null string # " << (pos - v.begin())<< std::endl;  
            pd.restart(v.size());  
            pd += (pos - v.begin() + 1);  
        }  
    }  
} 

test_progress_display_restart()运行的结果:

0%   10   20   30   40   50   60   70   80   90   100%  
|----|----|----|----|----|----|----|----|----|----|  
******  
Error: null string # 10  
  
0%   10   20   30   40   50   60   70   80   90   100%  
|----|----|----|----|----|----|----|----|----|----|  
*************  
Error: null string # 23  
  
0%   10   20   30   40   50   60   70   80   90   100%  
|----|----|----|----|----|----|----|----|----|----|  
***************************************************