CSDN博客

img coolcch

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

发表于2004/3/29 10:24:00  518人阅读

(如果没看过"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; }
0 0

相关博文

我的热门文章

img
取 消
img