1.1 初步跟踪的实现
我们想要让trace 对象记录一些事件消息,比如进入某个函数,离开某个函数,以及其他介入这两者之间的某些重要消息。如下:
C++ Code
|
1
2 3 4 5 6 7 8 |
int myFunction(int x)
{ string name = "myFunction"; Trace t(name); ... string moreInfo = "more interesting info"; t.debug(moreInfo); } |
我们下面的Trace类来实现这一功能。
C++ Code
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
class Trace
{ public: Trace(const string &name); ~Trace(); void debug(const string &name); static bool traceIsActive; private: string theFunctionName; }; inline Trace::Trace(const string &name): theFunctionName(name) { if(traceIsActive) { cout << "Enter function" << name << endl; } } inline void Trace::debug(const string &msg) { if(traceIsActive) { cout << msg << endl; } } inline Trace::~Trace() { if(traceIsActive) { cout << "Exit function" << theFunctionName << endl; } } |
1、I/O的开销是高昂的。
2、函数调用的开销是要考虑的一个因素,因此我们应该讲短小、频繁调用的函数内联。
3、复制对象的开销是高昂的,最好选择引用,而不是传值。
我们的做法是尽量少定义string类型。减少对象的定义和销毁的代价。利用const char *代替string来实现,下面的是完整代码。
C++ Code
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
#include<iostream>
#include<string> #include<windows.h> using namespace std; /* class Trace { public: Trace(const string &name); ~Trace(); void debug(const string &name); static bool traceIsActive; private: string theFunctionName; }; inline Trace::Trace(const string &name):theFunctionName(name) { if(traceIsActive) { cout<<"Enter function"<<name<<endl; } } inline void Trace::debug(const string &msg) { if(traceIsActive) { cout <<msg<<endl; } } inline Trace::~Trace() { if(traceIsActive) { cout<<"Exit function"<<theFunctionName<<endl; } }*/ //改进版 class Trace { public: Trace(const char *name); ~Trace(); void debug(const string &name); static bool traceIsActive; private: string *theFunctionName; }; inline Trace::Trace(const char *name):theFunctionName(0) { if(traceIsActive) { cout<<"Enter function"<<name<<endl; theFunctionName=new string(name); } } inline void Trace::debug(const string &msg) { if(traceIsActive) { cout <<msg<<endl; } } inline Trace::~Trace() { if(traceIsActive) { cout<<"Exit function"<<*theFunctionName<<endl; delete theFunctionName; } } bool Trace::traceIsActive=true; int addOne(int x) { char *name="addOne"; Trace t(name); return x+1; } int main() { SYSTEMTIME t1,t2; int j=10000000; int y=0; Trace::traceIsActive=false; GetSystemTime(&t1); for(int i=0;i<j;i++) { y=addOne(i); } GetSystemTime(&t2); cout<<t2.wMilliseconds-t1.wMilliseconds<<endl; system("pause"); } |
1.2 要点
1、对象定义触发隐形地执行构造函数和析构函数。我们称其为“隐形执行”而不是“隐形开销”,是因为对象的构造和销毁并不总是意味着产生开销。内联函数使用减少函数调用的开销。 2、通过引用传递对象还是不能保证良好的性能,所以避免对象的复制的确有利于提高性能。
3、不要把精力浪费在计算结果根本不会被使用的地方。
4、在完成同样的简单工作,char指针有时比string对象更加有效。
5、内联消除了常被使用的小函数调用所产生的函数开销。
本文介绍了一种在C++中实现函数跟踪调试的方法,并通过优化减少了性能损耗。文章详细展示了如何使用Trace类记录函数的进出及调试信息,并讨论了性能测试结果及优化措施。
4576

被折叠的 条评论
为什么被折叠?



