C++的profile辅助模板类 升级版

类别:编程语言 点击:0 评论:0 推荐:

(如果没看过"C++的profile辅助模板类" 先去看看那里的说明部分
http://www.csdn.net/Develop/read_article.asp?id=26029 )

先看例子:
  PROCEDURE_TIMEX(1, "Sleep(200)", Sleep(200));
  for (char i = 0; i != 5; ++i)
  {
    TOTAL_COUNTX(2, "for");
    TOTAL_TIMEX(3, "for");
    rt = FUNC_TIMEX(4, "MySleep(200)", MySleep(200));
  }
运行完后结果:
4 "MySleep(200)": 5 times, 1.00 seconds.
3 "for": 5 times, 1.00 seconds.
2 "for": 5 times.
1 "Sleep(200)": 1 times, 0.20 seconds.
还是很方便吧?

标志(就是这些宏的第一个参数)
还是只能为非负整数
用相同的数做标志 计时/计数结果叠加(TOTAL_COUNT只与TOTAL_COUNT叠加)
出结果时 这些宏的第二个参数会显示在标志的后面
其实偷懒一点 第二个参数可以不用引号引起来 如
  PROCEDURE_TIMEX(1, Sleep(200), Sleep(200));
但那样代码会看起来比较乱

另外 看了 PROCEDURE_TIME 或 PROCEDURE_TIMEX 的代码你就会发现
其实可以这样用:
  PROCEDURE_TIMEX(1, Several statements,
   {
    TOTAL_COUNTX(2, "for");
    TOTAL_TIMEX(3, "for");
    rt = FUNC_TIMEX(4, "MySleep(200)", MySleep(200));
   }
  );

注意:
1. 如果你前后两次用了同一个标志 但显示的字符串设的不同
最后显示结果时 以最后一次设的字符串为准
在实现时我用静态变量初始化的方法 这样基本上去掉了额外开销
(要注意静态变量只初始化一次 所以 到底哪里才是最后一次设的要想想清楚)
如:
 for (int i = 0; ; ++i)
 {
  PROCEDURE_TIMEX(1, "Sleep(200)", Sleep(200));
  if (i == 1) break;
  FUNC_TIMEX(1, "MySleep(200)", MySleep(200));
 }
运行完后结果是:
1 "MySleep(200)": 3 times, 0.60 seconds.

2. 如果一个标志在很多地方用 你想要把那些初始化的开销也去掉
就用后面不带X的那个版本
然后在别的地方用类似
SET_COUNT_NAME(1, "for count only")

SET_TIMER_NAME(1, "for else")


再次祝大家用得愉快!


以下代码用 VC6 GCC 编译运行通过

//filename: ShowRunTime.h #ifndef SHOWTIME_H #define SHOWTIME_H #include <stdio.h> #include <windows.h> #include <time.h> template <int I> class CShowRunTimesAss { public: unsigned int total_times; CShowRunTimesAss() { total_times = 0; } ~CShowRunTimesAss() { if (total_times == -1) return; char tmp[256]; sprintf(tmp, "\n%d %s: %u times.\n", I, GetName(), total_times); printf(tmp); OutputDebugString(tmp); } static void AddShowRunTimes() { static CShowRunTimesAss<I> tt; ++tt.total_times; } static char* GetName() { static char str[128]; return str; } CShowRunTimesAss(const char* const str) { total_times = -1; strncpy(GetName(), str, 127); } }; template <int I> class CShowRunTimeAss { public: unsigned int total_time; unsigned int total_times; CShowRunTimeAss() { total_time = total_times = 0; } ~CShowRunTimeAss() { if (total_times == -1) return; char tmp[256]; sprintf(tmp, "\n%d %s: %u times, %4.2f seconds.\n", I, GetName(), total_times, (double)total_time / CLOCKS_PER_SEC); printf(tmp); OutputDebugString(tmp); } static char* GetName() { static char str[128]; return str; } CShowRunTimeAss(const char* const str) { total_time = total_times = -1; strncpy(GetName(), str, 127); } }; template <int I> class CShowRunTime { public: CShowRunTime() { ShowRunTimeBegin(); } ~CShowRunTime() { ShowRunTimeEnd(); } static CShowRunTimeAss<I>& Gettt() { static CShowRunTimeAss<I> tt; return tt; } static bool ShowRunTimeBegin() { //Gettt().total_time -= clock(); // more slowly Gettt().total_time -= GetTickCount(); return true; } template <typename T> static T ShowRunTimeEnd(T t) { //Gettt().total_time += clock(); Gettt().total_time += GetTickCount(); ++Gettt().total_times; return t; } static bool ShowRunTimeBegin(const char* const str) { static CShowRunTimeAss<I> t(str); //Gettt().total_time -= clock(); Gettt().total_time -= GetTickCount(); return true; } static void ShowRunTimeEnd() { //Gettt().total_time += clock(); Gettt().total_time += GetTickCount(); ++Gettt().total_times; } }; ////////////////////////////////////////////////////////////////////////// #define TOTAL_TIME_BEGIN(I) \ CShowRunTime<I>::ShowRunTimeBegin() #define TOTAL_TIME_END(I, X) \ CShowRunTime<I>::ShowRunTimeEnd(X) #define TOTAL_COUNT(I) \ do { CShowRunTimesAss<I>::AddShowRunTimes(); } while (0) #define TOTAL_TIME(I) \ CShowRunTime<I> _ShowRunTime_##I #define PROCEDURE_TIME(I, X) \ do { CShowRunTime<I> _ShowRunTime_; X; } while (0) #define FUNC_TIME(I, X) \ (TOTAL_TIME_BEGIN(I) ? TOTAL_TIME_END(I, X) : TOTAL_TIME_END(I, X)) #define REF_FUNC_TIME(I, X) \ (TOTAL_TIME_BEGIN(I) ? *TOTAL_TIME_END(I, &(X)) : *TOTAL_TIME_END(I, &(X))) #define SET_COUNT_NAME(I, S) \ static CShowRunTimesAss<I> _Set_ShowRunTimes_Name_##I(#S) #define SET_TIMER_NAME(I, S) \ static CShowRunTimeAss<I> _Set_ShowRunTime_Name_##I(#S) #define TOTAL_TIME_BEGINX(I, S) \ CShowRunTime<I>::ShowRunTimeBegin(#S) #define TOTAL_COUNTX(I, S) \ do { SET_COUNT_NAME(I, S); CShowRunTimesAss<I>::AddShowRunTimes(); } while (0) #define TOTAL_TIMEX(I, S) \ SET_TIMER_NAME(I, S); CShowRunTime<I> _ShowRunTime_##I #define PROCEDURE_TIMEX(I, S, X) \ do { SET_TIMER_NAME(I, S); CShowRunTime<I> _ShowRunTime_; X; } while (0) #define FUNC_TIMEX(I, S, X) \ (TOTAL_TIME_BEGINX(I, S) ? TOTAL_TIME_END(I, X) : TOTAL_TIME_END(I, X)) #define REF_FUNC_TIMEX(I, S, X) \ (TOTAL_TIME_BEGINX(I, S) ? *TOTAL_TIME_END(I, &(X)) : *TOTAL_TIME_END(I, &(X))) #endif // #ifndef SHOWTIME_H

//filename: main.cpp #include <iostream> #include "ShowRunTime.h" using namespace std; class ctest1 { public: ctest1(const ctest1& rhs) { cout << "ctest1() copy\n"; } ctest1() { cout << "ctest1()\n"; } ~ctest1() { cout << "~ctest1()\n"; } }; ctest1 ftest1() { cout << "ftest1()\n"; return ctest1(); } int testval() { cout << "testval()" << endl; return 0; } int& testref() { static int i; cout << "testref() " << i << endl; return i; } const int& testconstref() { static int i; cout << "testconstref() " << i << endl; return i; } int MySleep(DWORD dwMilliseconds) { Sleep(dwMilliseconds); return 0; } int main() { {TOTAL_TIMEX(0, "main"); ctest1 t; int rt, i; cout << "call ftest1 direct\n"; ftest1(); cout << "/call ftest1 direct\n"; cout << "call ftest1 indirect\n"; FUNC_TIMEX(1, "ftest1", ftest1()); cout << "/call ftest1 indirect\n"; cout << endl; testref() = 1; // testconstref() = 2; // testval() = 3; REF_FUNC_TIMEX(10, "testref", testref()) = 4; // REF_FUNC_TIME(10, testconstref()) = 5; // VC6 Error! // Should not be OK. assignment of read-only location! // REF_FUNC_TIME(10, testval()) = 6; cout << "call testref direct\n"; cout << "result address is: " << (int)&testref() << endl; cout << "/call testref direct\n"; cout << "call testref indirect\n"; cout << "result address is: " << (int)&REF_FUNC_TIMEX(11, "testref", testref()) << endl; cout << "/call address indirect\n"; cout << endl; PROCEDURE_TIMEX(11, "Sleep", Sleep(200)); for (i = 0; i != 5; ++i) { TOTAL_COUNTX(2, "for"); TOTAL_TIMEX(3, "for"); rt = FUNC_TIMEX(4, "MySleep", MySleep(200)); } PROCEDURE_TIMEX(12, for several statements, { cout << "call ftest1 indirect once again\n"; FUNC_TIMEX(1, "ftest1", ftest1()); cout << "/call ftest1 indirect once again\n"; cout << "call ftest1 indirect once again, and use another counter\n"; FUNC_TIMEX(5, "ftest1", ftest1()); cout << "/call ftest1 indirect once again, and use another counter\n"; } ); for (i = 0; ; ++i) { PROCEDURE_TIMEX(13, "Sleep(200)", Sleep(200)); if (i == 1) break; FUNC_TIMEX(13, "MySleep(200)", MySleep(200)); } } //TOTAL_TIMEX(0, main); // SET_TIMER_NAME(13, "Sleep(200) MySleep(200) Sleep(200)");
// system("PAUSE"); return 0; }

本文地址:http://com.8s8s.com/it/it28940.htm