[C++] 能否設計一個一般的計時函數?

我有這樣一段 code block:

實現的功能是

1. 運行 dmet 下的 _bs_dmet_ () 方法

2. 計時

由於我的程序中有好多個地方需要計時,我在想有沒有辦法寫一個函數實現上述功能,但更加 general,比如這樣調用:

更一般的,允許有參數,參數用類似 tuple 的數據結構加在後面,如:

在 C++ 的框架下這是可能實現的嗎(我知道 python 可以很容易實現)?如果不能,那麼是語言的哪個性質限制了它呢?

提前感謝!!!


void timeit(std::function& func)
{
Timer t;
t.start();
func();
t.stop();
printf("%.4f secs
", t.seconds();
}

timeit(some_function);
timeit([]{ some_function(arg1, arg2); });


把 陳碩老師的答案稍微改變下 以下代碼基於C++17 標準

template &
decltype(auto) timed_invoke(Callable callable, Args ...args)
{
struct timer{
timer(){
t0 = high_resolution_clock::now();
}
~timer(){
auto t1 = high_resolution_clock::now();

std::cout &<&< (t1 - t0).count() &<&< "nonoseconds. "; } time_point& t0;
} t;
return std::invoke(callable, std::forward&(args)...);
}

改成這樣後 就可以這樣調用

int* func0(int x, int y, const char* z) {
return nullptr;
}

void func1(int x, const char* z) {
return;
}

void func2() {
return;
}

template&
void func3(T x) {
return;
}

struct S {
int member_func(int x, float y) {
return x;
}

bool operator()() {
return false;
}

void operator()(int x) {
return;
}
};

int main() {

int* ret = timed_invoke(func0, 1, 2, "hello");
timed_invoke(func1, 1, "hello");
timed_invoke(func2);
timed_invoke(func3&, 2); // template function

auto h = timed_invoke([]{return "hello"; }); // lambda

S s;

int r = timed_invoke(S::member_func, s, 1, 2.0f); // member function
bool r0 = timed_invoke(s); // bool S::operator()()
timed_invoke(s, 10); // void S::operator()(int)
}

這樣就滿足題主的需求了。


我還是推薦用傳統c++98,使用scope方案。

很多時候,我們不是測試一個函數,而是一段代碼。

為啥不用性能分析工具來替代這種入侵式的時間測試呢?


#define START_TIMER() tic()
#define STOP_TIMER(msg) printf("cost time of %s is %lfms
", msg, toc())
#define TIMER_BLOCK(msg) STAERT_TIMER(); auto __stop_timer_on_exit__=make_guard([]{STOP_TIMER(msg)};)

使用1:

START_TIMER();
some_heavy_func();
STOP_TIMER("some_heavy_func");

使用2:

{
TIMER_BLOCK("some_heavy_func");
some_heavy_func();
}

考慮如下:

  • 用宏定義,方便開關,如發布時。
  • 用start/end方式時,可以測試代碼段,且不影響測試代碼的作用域,如定義的變數外面非計時代碼還可以用。


class guard_timer
{
public:
guard_timer()
{
m_start = high_resolution_clock::now();
}
~guard_timer()
{
he::get_singleton().life_time += 1s;

milliseconds t = duration_cast&(
high_resolution_clock::now() - m_start);
cout &<&< "total time is " &<&< t.count() &<&<"ms." &<&< endl; } private: time_point& m_start;
};

#ifdef I_WANT_TIME_IT
#define TIME_IT guard_timer _timer();
#else
#define TIME_IT
#endif

{
TIME_IT;
dmet._bs_dmet();
}


題主的意思是這樣?

template&
T measure_function_time(Ret(*pFunc)(Args...), Args ... args)
{
high_resolution_clock::time_point tp1 = high_resolution_clock::now();
pFunc(args...);
high_resolution_clock::time_point tp2 = high_resolution_clock::now();
duration& dur = duration_cast&&>(tp2 - tp1);
return dur.count();
}

template&
T measure_function_time(Ret(C::*pFunc)(Args...), C* pC, Args ... args)
{
high_resolution_clock::time_point tp1 = high_resolution_clock::now();
(pC-&>*pFunc)(args...);
high_resolution_clock::time_point tp2 = high_resolution_clock::now();
duration& dur = duration_cast&&>(tp2 - tp1);
return dur.count();
}

不過不支持std::function和lambda和std::bind,要支持這幾個還是像陳碩老師那樣用std::function作參數吧。


推薦閱讀:

unity項目越大編譯速度越慢 ue4用藍圖秒編譯 背後分別的原因是什麼?
c++的強制類型轉換?
對於 計算機圖形/界面/可視化/遊戲畫面/遊戲引擎 的疑惑?
VS編寫C++程序,如何在一個工程裡面創建多個包含main函數的文件?
c++的单例模式为什么不直接全部使用static,而是非要实例化一个对象?

TAG:編程 | C編程語言 | C | CC | C11 |