通常我們在測試程式效能的時候,都需要一些計時的操作,計時的API調用林林總總,我自己比較喜歡使用的是boost庫裡面的timer,方便實用。不過對於需要分步計時的狀況(比如一個完整的處理過程要分成4步,我們希望得到每一步花費的時間和總共花費的時間),還需要寫滿多額外的代碼,而一個優秀的程式員應該遵循DRY - Don't repeat yourself 的原則 ^_^,所以自己寫了一個可用於分步計時的計時器。
PS:
string 和 vector 使用的都是QT庫的實現,需要的話也可以換成標準庫的實現。
KTimer.h#pragma once
#include <QString>
#include <QVector>
#include <boost/timer.hpp>
#include <utility>
namespace milk
...{
typedef std::pair<QString, double> STEP_RECOED;
typedef QVector<STEP_RECOED> PROCEDURE_RECORD;
/**//** A step markable timer, can record each step's used time in a
long process procedure. */
class KTimer
...{
private:
QString _name;
boost::timer _timer;
PROCEDURE_RECORD _record;
double _total;
public:
KTimer(const QString& name) : _name(name), _total(0)
...{
}
/**//** Restart. */
void restart()
...{
_timer.restart();
_record.clear();
_total = 0;
}
/**//** Mark current step and return itself. */
KTimer& mark() ...{return mark(QString("S %1").arg(_record.size() + 1));}
/**//** Mark with a name. */
KTimer& mark(const QString&);
/**//** Total elapsed time. */
double total() ...{return _total;}
/**//** Last step's used time. */
double lastStep() ...{return _record.last().second;}
/**//** Return the record of the whole procedure. */
PROCEDURE_RECORD record() const ...{return _record;}
/**//** Get String. */
QString toString() const;
};
}
KTimer.cpp
#include "KTimer.h"
namespace milk
...{
KTimer& KTimer::mark(const QString& name)
...{
_record.append(STEP_RECOED(name, _timer.elapsed() - _total));
_total = _timer.elapsed();
return *this;
}
QString KTimer::toString() const
...{
QString result = QString("[%1][%2][T %3] - ")
.arg(_name).arg(_record.size()).arg(_total, 4, 'f', 3);
foreach(STEP_RECOED record, _record)
...{
result += QString(" %1, %2s;")
.arg(record.first)
.arg(record.second, 4, 'f', 3);
}
return result;
}
}
一段使用的常式:
void CoreTest::testKTimer()
...{
milk::KTimer ktimer("KTimer Test");
Sleep(200);
std::cout<<qPrintable(ktimer.mark("First").toString())<<std::endl;
Sleep(300);
std::cout<<qPrintable(ktimer.mark("Second").toString())<<std::endl;
Sleep(100);
std::cout<<qPrintable(ktimer.mark("Third").toString())<<std::endl;
Sleep(500);
std::cout<<qPrintable(ktimer.mark("Last").toString())<<std::endl;
CPPUNIT_ASSERT( true );
}
輸出的結果: