`

Efficient C++ 第一章

 
阅读更多
转自
http://blog.chinaunix.net/uid-25872711-id-3013832.html

Efficient C++ 第一章


Charpter 1 The tracing war story
  很多时候,为了方便查找bug,会使用trace。比如用如下方式:
#ifdef TRACE
    Trace t("myFuction"); // Constructor takes a function name argument
    t.debug("Some information message");
#endif


    这样的方式不错,但是问题是:每次TRACE宏的开头都要重新编译代码。想到用如下方式避免这一问题:

void Trace::debug(string &msg)
{
    if (traceIsActive) {
      // log message here
      }
}


    加入一个traceIsActive变量来控制log开关,因为写log开销最大,这样看上去也算可行。下面看,假设有如下调用:
t.debug("x = " + itoa(x)); // itoa() converts an int to ascii


    即使,traceIsActive为false,上面的调用还是会产生如下开销:
    1) 创建一个临时string变量保存“x=”
    2) 调用itoa()函数
    3) 创建一个临时string变量保存itoa(x)返回的char*指针
    4) 连接两个字符串,组成第三个临时string变量
    5) debug return后,销毁所有临时变量

    这样下来对程序原有执行是大有影响的,尤其是在程序常用接口中加入TRACE,那将严重影响执行效率。

    最开始的实现
  我们实现的trace主要在函数调用开始,调用结束,和中间部分写log信息。
class Trace {
public:
    Trace (const string &name);
    ~Trace ();
    void debug (const string &msg);

    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;
     }
}

//调用

int myFunction(int x)
{
    string name = "myFunction";
    Trace t(name);
    ...
    string moreInfo = "more interesting info";
    t.debug(moreInfo);
    ...
}; // Trace destructor logs exit event to an output stream

    上面的trace实现,经过测试,程序加入trace前后,效率降低了20%之多!!!

问题在哪呢?
    工程师对C++执行会有不同的理解,但是如下是最基本可知的原则:
    1) I/0开销很大
    2) 经常调用,而且很简短的函数声明为inline
    3) 拷贝实例开销大,多传引用而不是实例

  而我们的代码都符合3条原则,问题在于创建了过多我们并未真正使用的实例,下面是Trace的最小用例,程序调用开始和结束时写log记录。
int myFunction(int x)
{
    string name = "myFunction";
    Trace t(name);
    ...
};

    它包含了如下开销:
    1)创建string实例name保存“myFunction”
    2) 调用Trace的构造函数
    3)Trace的构造函数调用string的构造函数,来初始化string成员
    (函数调用结束时)
    4)析构string实例name
    5)调用Trace的析构函数
    6)Trace析构函数调用string的析构函数,销毁string成员

  实际上,当我们不要用Trace做log,上面这些实例都是完全无用的,这些开销白白浪费掉了。来做如下测试:
int addOne(int x) // Version 0
{
    return x+1;
}
int main()
{
    Trace::traceIsActive = false;//Turn tracing off
    //...
    GetSystemTime(&t1); // Start timing

    for(i =0; i < j; i++) {
       y = addOne(i);
       }

    GetSystemTime(&t2); // Stop timing
    // ...
}

    我们将函数修改为如下,对比前后执行时间:
int addOne(int x) // Version 1. Introducing a Trace object
{
    string name = "addOne";
    Trace t(name);

    return x+1;
}

    执行结果显示,前后执行时间为55ms和3500ms,相差了超过60倍!!!!

The Recovery Plan
  修改1,把addOne中创建的string实例name换成Char*,修改如下:
int addOne(int x) // Version 2. Forget the string object.
                      // Use a char pointer instead.
{
    char *name = "addOne";
    Trace t(name);

    return x+1;
}
//做上面修改,同时Trace构造函数修改为:
inline
Trace::Trace(const char *name) : theFunctionName(name)// Version 2
{
    if (traceIsActive){
        cout << "Enter function" << name << endl;
    }
}


    这样,我们去除了name string实例的创建和析构的开销,执行时间由3500ms降到2500ms。
  下一步,去除Trace中string成员变量的不必要开销,成员变量用string指针代替,使用指针的好处是调用构造时,不会自动调用成员的构造函数,只是初始化指针值。我们可以辨别Trace状态,再调用构造函数。

class Trace { //Version 3. Use a string pointer
public:
    Trace (const char *name) : theFunctionName(0)
    {
    if (traceIsActive) { // Conditional creation
       cout << "Enter function" << name < endl;
       theFunctionName = new string(name);
       }
    }

    ...
private:

    string *theFunctionName;
};


inline
Trace::~Trace()
{
    if (traceIsActive) {
       cout << "Exit function " << *theFunctionName << endl;
       delete theFunctionName;
       }

}

    通过这一步优化,Trace中string实例的不必要开销也消除了。执行时间降到了185ms。

Key Point
  1)不要传实例,多用引用
  2)常用的简单函数声明为inline
  3)I/O开销大
  4)尽量减小可能不被使用成员的调用构造、析构函数
分享到:
评论

相关推荐

    Efficient C++

    《Efficient C++》是一本深受C++程序员喜爱的经典书籍,它主要关注如何在C++编程中实现高效、优化的代码。这本书的核心理念是帮助开发者理解C++的底层机制,以便编写出性能更高、资源利用更合理的程序。作者通过一...

    Efficient C++中文版

    《Efficient C++中文版》作为一本专注于高效使用C++的书籍,其内容覆盖了C++编程中的许多高级概念和最佳实践。以下是对该书一些核心知识点的总结和解释: 1. 预处理器指令#define 预处理器指令#define用于定义宏。...

    Efficient C++ 英文 CHM 非扫描版

    Efficient C++ 英文 CHM 非扫描版 Dov Bulka David Mayhew

    Efficient C++提高C++性能的编程技术.rar

    《Effective C++: 提高C++性能的编程技术》是一本经典的C++性能优化指南,由Scott Meyers撰写。这本书深入探讨了如何通过编写高效、简洁的代码来最大化C++程序的性能。以下是对该书内容的一些关键知识点的概述: 1....

    Efficient C++: Performance Programming Techniques

    《Efficient C++: Performance Programming Techniques》是一本深入探讨如何在C++编程中实现高效性能的书籍。由IBM的资深软件专家Scott Meyers和Barbara E. Moo共同撰写,这本书结合了他们在处理高要求性能系统时...

    Efficient C++ Performance Programming Techniques.rar

    《Efficient C++ Performance Programming Techniques》是一本深入探讨C++性能优化的经典著作,作者是Scott Meyers。这本书针对C++程序员提供了许多实用的技巧和策略,帮助他们在编写代码时能够兼顾效率与性能。以下...

    Efficient C++ Performance Programming Techniques

    《Efficient C++ Performance Programming Techniques》是一本专为C++程序员设计的性能优化指南,它深入探讨了如何在C++编程中实现高效的代码执行。这本书不仅涵盖了基础的编程技巧,还涉及了许多高级主题,旨在帮助...

    Efficient.C++ Performance Programming Techniques

    《Effective C++:性能编程技术》是一本深受程序员喜爱的经典书籍,主要针对C++语言的高效性能优化提供了诸多实用技巧和建议。这本书深入探讨了如何通过优化代码来提高C++程序的运行效率,同时保持代码的清晰性和可...

    efficient c++电子版

    相当经典的一本C++书!学习C++必备。

    Modern and efficient C++ Thread Pool Library.zip

    "Modern and efficient C++ Thread Pool Library"很可能是一个第三方库,旨在提供比标准库更高级、性能更好的线程池实现。这个库可能包含以下关键知识点: 1. **线程池概念**:线程池是一组预先创建的线程,等待...

    Effective C++ 3个版本清晰pdf

    - **第一版到第二版**:主要增加了对C++98新特性的讨论,如模板和异常处理。 - **第二版到第三版**:针对C++11及后续标准进行了更新,涵盖了新的语言特性,如lambda表达式、右值引用和类型推断等。 通过阅读这三...

    Real-Time C++ Efficient Object-Oriented and Template Programming(3rd) 无水印原版pdf

    Real-Time C++ Efficient Object-Oriented and Template Microcontroller Programming(3rd) 英文无水印原版pdf 第3版 pdf所有页面使用FoxitReader、PDF-XChangeViewer、SumatraPDF和Firefox测试都可以打开 本...

    Effective C++ 中文版第三版 高清PDF.pdf

    《Effective C++ 中文版第三版》是一本深入探讨C++编程实践的书籍,由Scott Meyers撰写,旨在帮助读者提升C++编程的效率和专业性。这本书的高清PDF版本提供了一个清晰易读的阅读体验,是C++程序员进阶学习的理想资料...

    Efficient.C++Performance.Programming

    《Efficient C++ Performance Programming Techniques》是一本针对C++程序员的性能优化指南,由Scott Meyers撰写,是计算机科学的经典著作之一。这本书深入探讨了如何通过优化C++代码来提高程序运行效率,对于想要...

    Real-Time C++ Efficient Object-Oriented and Template Microcontroller Programming

    综上所述,《实时C++:高效面向对象与模板微控制器编程》是一本深入探讨如何使用C++语言进行实时系统开发的专业书籍。它不仅提供了理论上的指导,还结合了大量的实践案例,旨在帮助开发者掌握高效的实时系统编程技巧...

Global site tag (gtag.js) - Google Analytics