1.概述
timer是一个很小的库,提供简易的度量时间和进度显示功能,可以用于性能测试等需要计时的任务,对于大多数情况足够应付。
timer库包含三个组件,分别是:计时器类timer、progress_timer和进度指示类progress_display。
2.timer
2.1 用法
timer类可以测量时间的流逝,是一个小型计时器,提供毫秒级别的计时精度和操作函数,就像是一个方便的秒表。
timer位于命名空间boost,为了使用timer组件,包含头文件<boost/timer.hpp>
实例:
#include<boost/timer.hpp>
using namespace boost;
int main(){
timer t;
cout<<"max timespan:"<<t.elapsed_max() / 3600<<"h"<<endl;//可度量最大时间,小时为单位。
cout<<"min timespan:"<<t.elapsed_min()<<"s"<<endl;//可度量最小时间,以秒为单位。
cout<<"now time elapsed:"<<t.elapsed()<<"s"<<endl;
}
程序输出如下:
max timespan:596.523h
min timespan:0.001s
now time elapsed:0.015s
2.2 类摘要
<span style="font-family:SimSun;font-size:14px;">class timer{
public:
timer(){_start_time = std::clock();}
void restart(){_start_time = std::clock();}
double elapsed() const{
return double(std::clock() - _start_time) / CLOCKS_PER_SEC;}
double elapsed_min() const{
return double(1)/double(CLOCKS_PER_SEC);}
double elapsed_max() const{
return (double((std::numeric_limits<std::clock_t::max>)())-double(_start_time))/double(CLOCKS_PER_SEC);}
private:
std::clock_t_start_time;
};</span>
timer的计时使用了标准库头文件<ctime>里的std::clock()函数,它返回自进程启动以来的clock数,每秒的clock数由宏CLOCK_PER_SEC定义,CLOCK_PER_SEC的值因操作系统而不同。
timer没有定义析构函数,因为它仅有一个类型为clock_t的成员变量_start_time,故没有资源可释放。这样做是正确且安全的。
2.3 建议
timer接口简单,轻巧好用,但不适合高精度的时间测量任务,它的精度依赖于操作系统或编译器,难以做到跨平台。也不适合大跨度时间段测量,可提供的最大时间跨度只有几百个小时。
3 progress_timer
progress_timer 也是一个计时器,它继承自timer,会在析构时自动输出时间,省去了手动调用elapsed()的工作,对外输出精度为小数点后两位。progress_timer位于名字空间boost,头文件为<boost/progress.hpp>。
3.1类摘要
class progress_timer:public timer,noncopyable{
public:
explicit progress_timer();
progress_timer(std::ostream& os);
~progress timer();
};
构造函数progress_timer(std::ostream& os),它允许将析构时的输出定向到指定的IO流里,默认是std::cout。如果有特别的需求,可以用到其他标准库输出流(ofstream、ostringstream)替换,或者用cout.rdbuf()重定向cout的输出(但需记得及时回复cout的状态以免发生未知错误)。
例:
stringstream ss;
{
progress_timer t(ss);
}
cout<<ss.str();
3.2用法
progress_timer继承了timer的全部能力,可以如timer一样使用,如:
progress_timer t;
...
cout<<t.ellapsed()<<endl;
但有更简单的用法,不需要任何调用,只要声明progress_timer对象就可以了:
#include<boost/progress.hpp>
int main(){
boost::progress_timer t;
//do sth...
}
程序退出导致progress_timer析构时,会自动输出流失的时间。显示输出:
0.23s
如果要在一个程序中测量多个时间,可以用花括号限定progress_timer的生命周期:
<pre class="cpp" name="code">#include<boost/progress.hpp>
int main(){
{
boost::progress_timer t;
//do sth...
}
{
boost::progress_timer t;
//do sth...
}
...
}
4 progress_display
progress_display可以在控制台上显示程序的执行进度,如果程序执行很耗费时间,那么它能够提供一个有好的用户界面,不至于让用户在等待中失去耐心。
progress_display位于名字空间boost,为了使用progress_display组件,需要包含头文件<boost/progress.hpp>。
4.1 类摘要
progress_display是一个独立的类,与timer库中其他两个组件没有任何联系,类摘要如下:
class progress_display:noncopyable{
public:
progress_display(unsigned long expected_count);
progress_display(unsigned long expected_count,
std::ostream& os,
const std::string & s1 = "\n",
const std::string & s2 = "",
const std::string & s3 = "" );
void restart(unsigned long expected_count);
unsigned long operator+=(unsigned long increment);
unsigned long operator++();
unsigned long count() const;
unsigned long expected_count() const;
};
progress_display构造函数接受一个long型参数expected_count,表示进度显示的基数,是最长用的创建方法。另一种形式的构造函数除了基数和流输出对象外,还接受三个字符串参数,定义显示的三行首字符串。
在构造后progress_display对象会显示出一个类似windows进度条的界面,如下:
0% 10 20 30 40 50 60 70 80 90 100%
|----|----|----|----|----|----|----|----|----|----|----|
重载的加法符operator+=和operator++用来增加计数,并在第三行用字符*显示进度百分比count()/expected_count。成员count()可以返回当前的计数,当技术达到基数expected_count时表示任务已经完成,进度为100%。
4.2 用法
#include<boost/progress.hpp>
using namespace boost;
int main(){
vector<string> v(100);
ofstream fs("c:\\test.txt");
progress_display pd(v.size());
vector<string>::iterator pos;
for(pos = v.begin();pos!=end();++pos){
fs<<*pos<<endl;
++pd;
}
}
}
4.3 注意事项
progress_display的固有缺陷,无法把进度显示输出与程序的输出分离。如果使用progress_display的程序也有输出操作,那么进度显示会一片混乱。
一个可能(但愿非常完美)的办法是在每次显示进度都调用restart()重新显示进度刻度,然后用operator+=来指定当前进度,而不是简单地调用operator++,如:
pd.restart(v.size());
pd+=(pos - v.begin()+1);