C++ 性能/内存优化指南

Posted

技术标签:

【中文标题】C++ 性能/内存优化指南【英文标题】:C++ Performance/memory optimization guidelines 【发布时间】:2010-03-31 18:19:26 【问题描述】:

有人有 C++ 内存优化指南的资源吗?最佳实践、调优等?

举个例子:

Class xxx 

    public: 
        xxx();
        virtual ~xxx();

    protected:

    private:

;

由于在这个类中没有受保护和私有的项目,编译器或内存分配是否有任何好处来摆脱受保护和私有?

更新:什么是程序员这样做:

Class xxx 

    public: 
        xxx();
        virtual ~xxx();

    public:
        more stuff();
        more();

   ifndef __BUILD_WIN__
      public:
        even more();
        envenmore2();
   endif
    protected:

    private:

;

【问题讨论】:

您能否添加有关您正在工作的问题域的任何信息? 【参考方案1】:

有人有 C++ 内存优化指南的资源吗?最佳实践、调优等?

这在很大程度上取决于您的编译器和目标环境(RISC、Unix/Linux、Windows)。大多数编译器都会有这样的信息。

有一些实用程序可以让您跟踪内存泄漏,以便您可以在测试期间修复它们。如果您要动态分配很多东西(通常是 C/C++ 的情况),请尝试确保在销毁对象之前释放所有内容。为此:

如果您重视内存而不是处理器,请使用smart pointers。 如果您的类有任何成员变量是指针,请确保您的析构函数释放每个成员变量。在源代码中将成员变量组合在一起,以便将这些变量与析构函数进行比较。 尽可能避免动态内存分配以避免泄漏。优先使用std::string 而不是动态分配的char* 等。

是否有任何好处 编译器或内存分配来获取 摆脱 protected 和 private 以来 没有项目是 在此类中受保护和私有?

不,如果我没记错的话,protected/private 仅在编译期间检查,因此即使关键字下有项目,它们也不会影响性能。

此外,重要的是要了解编译器非常智能(通常比程序员更聪明),因此它会优化任何可以优化的东西;例如,让我们在构造函数中声明一个变量int a。假设你根本不使用它,你只是把它忘在那里了。大多数编译器甚至不会为这些变量节省堆栈空间。其他人将需要用户激活优化才能发生这种情况,但根据经验,您的任何程序的生产版本都应该在启用优化的情况下编译,即使不是完整的。

关于更新,您看到的是预处理器指令,用于执行所谓的选择性编译。看看here。

【讨论】:

@bruno - 谢谢,有帮助。编译器比程序员更聪明,但是程序员编写编译器,所以至少有几个程序员必须足够聪明才能让编译器完成所有这些工作!现在看看 XCode 将如何告诉我未使用的项目,因为知道会很好! @ML:我从未使用过 XCode(它是 Apple 的目标 IDE,不是吗?)但可能有一些方法可以做到。编译器掌握了许多***程序员的知识,这就是他们比普通程序员更聪明的原因。卡斯帕罗夫是世界上最好的棋手,却被人创造的软件打败了! (这就是我喜欢计算机的原因,尽管我希望 Kasparov 能够胜过 DeepBlue)。 编译器比程序员更“聪明”,因为他们比人类更容易同时考虑多种优化。个别优化可能没有那么困难,但同时始终如一地应用所有优化。 @bruno - 看看我对帖子的更新。这会改变你的想法吗?只是程序员做的愚蠢的事情? 我非常不同意destructor 的评论:不要在类中使用原始指针......你忘记了那里的复制和赋值操作,它们会导致 UB。【参考方案2】:

编译器不必解析它们,所以编译器有这个好处。值得(不是很多)。

应该没有内存使用差异。

除此之外,我能想到的唯一好处是阅读代码的人必须处理的麻烦更少(并不是说在您的示例中它特别繁琐)。

【讨论】:

我也同意如果省略不必要的关键字,代码阅读会更容易。【参考方案3】:

有 Dov Bulka 和 David Mayhew 的“Efficient C++: Performance Programming Techniques”。我不认为它具有开创性,但它肯定是一本有趣的读物,它教授了一些基础知识。

【讨论】:

【参考方案4】:

public、protected 和 private 关键字,根本不要将其放入目标文件中,因此根本没有任何好处。

一般

尽量避免分配和释放内存,尽可能重复使用。遍历堆特别慢。 完成后释放内存。除非有强大的性能原因,否则不要闲逛。

事实上,与 Java 不同的是,在使用 C++ 编程时,您总是需要考虑内存管理以避免泄漏。因此,优化比 Java 更自然

【讨论】:

@deus 我用 C++ 编程时几乎从不考虑内存管理。 应该阅读:“事实是,与 Java 不同,C++ 允许您编写和使用包装器来为您提供确定性的自动内存管理,因此您无需考虑内存管理以避免泄漏。”【参考方案5】:

就一般指南而言,有 What Every Programmer Should Know About Memory,但我不确定它是否是您要查找的内容。

在结构或类中优化内存的一般准则是将数据成员从最大到最小排序。这可以防止多余的填充浪费您的结构或类中的空间。

关于你的问题,我认为已经得到了适当的回答,但你可以使用 sizeof() 比较自己。

【讨论】:

【参考方案6】:

这真的取决于您的应用程序。如果您在进行模拟或任何类型的科学计算,在大型内存阵列上进行浮点计算,那么您可以做很多事情。

优化缓存重用(缓存阻塞、填充等) 优化以最大限度地减少 TLB 命中(页面错误) 将数据排列为数组结构,而不是结构数组 避免不必要的内存清除 避免重新分配内存,而是重用

如果您需要拥有许多小对象,请查看享元设计模式或对象池之类的东西。

至于担心privateprotected 声明,不用担心。它们仅与编译相关以强制封装和数据隐藏,不会影响生成的二进制文件。

【讨论】:

【参考方案7】:

由于在这个类中没有受保护和私有的项目,编译器或内存分配是否有任何好处来摆脱受保护和私有?

没有。 AFAIK,非虚拟方法不会增加类实例的大小。

有人有 C++ 内存优化指南的资源吗?

1) 如果您关心性能,请使用分析器(例如 AQtime)。不要猜测,使用工具。 2) 一般来说,频繁(每秒数_millions_次)分配和释放内存(使用new/delete)并不是一个好主意,尤其是大块。根据我的经验,这种使用会导致性能损失。如果您经常需要使用相同的例程分配大块内存(使用 new 或 std::vector),请考虑在下一次调用中重用相同的块(这在多线程应用程序中会很棘手)。 IE。而不是

void doStuff(int memSize)
    std::vector<char> buf(memSize);
    //..some code here

使用这样的东西:

void doStuff(int memSize)
    static std::vector<char> buf;
    if (buf.size() < memSize)
        buf.resize(memSize);
    //..some code here

但仅在必要时,并且仅当您绝对确定不能从多个单独的线程同时调用此例程时。 (要使其与多线程兼容,您需要一些技巧 - 互斥锁或多个缓冲区的“池”) 3) 在堆栈上分配超过 1 兆字节(对于 windows)或 8 兆字节(对于 linux)将导致您的程序崩溃(win 堆栈溢出,linux 上的段错误),除非您在编译时指定堆栈大小。示例:

void doStuff()
    char buf[1024*1024*12];//use new[] or std::vector instead of this.
    //some code here

我能想到的就这些了。

【讨论】:

【参考方案8】:

优化技术 C语言优化代码的三种技术:

计算绑定技术 内存绑定技术 输入/输出绑定技术

计算绑定技术涉及计算执行运算符和函数所花费的时间。计算绑定技术包括:

分析 内联 循环展开 环路干扰 循环不变量计算 循环反转 尾递归消除 查表

在内存受限的计算中,您需要考虑程序使用的内存。使用来自内存层次结构较低部分的内存会增加执行时间。在运行程序时,您需要使用适当级别的内存。内存绑定技术包括:

参考地点 行主要寻址 填充减少 内存泄漏

在输入/输出 (I/O) 绑定优化中,使用顺序访问和随机访问方法来减少检索信息所需的时间。

缓冲 I/O 比无缓冲 I/O 快。您可以对大缓冲区使用 read() 和 write() 函数。您可以使用 mmap() 来减少检索信息所需的时间。 Mmap() 将进程的地址空间映射到共享内存或文件。

更多优化技术是:

尽量减少程序中全局变量的使用。

在文件中将除全局变量以外的所有函数声明为静态函数。

使用字长变量,例如 int 和 float,而不是 char、short 和 double。

避免使用递归。

避免使用 sqrt() 函数,因为它是 CPU 密集型的。

使用一维数组。

不要将密切相关的函数拆分成单独的文件。

使用 puts() 函数代替 printf 函数。

使用未格式化/二进制文件访问而不是格式化文件访问。

如果编译器支持这个函数来控制 malloc 函数,使用 mallopt()。

使用宏而不是小函数来节省 CPU 时间。

【讨论】:

以上是关于C++ 性能/内存优化指南的主要内容,如果未能解决你的问题,请参考以下文章

Android性能优化解析-内存抖动 附:《Android性能优化指南》

Android性能优化——360°全方面性能调优指南(含内存优化布局优化实战解析等)

Android性能优化——360°全方面性能调优指南(含内存优化布局优化实战解析等)

Android性能优化:Github下载超10万次的360°全方面性能调优指南(含内存优化布局优化实战解析等)

C++应用程序性能优化——操作系统的内存管理

Android性能优化:这是一份Github下载超10万次的360°全方面性能调优指南(含内存优化布局优化等)