c - 如何针对内存使用优化 GCC 编译?

标签 c gcc

我正在开发一个应该使用尽可能少的内存的库(我不关心其他任何,比如二进制大小或速度优化)。

是否有我可以使用的任何 GCcflags(或任何其他 GCC 相关选项)?我应该避免某种程度的 -O* 优化吗?

最佳答案

您的库 - 或惯用 C 中的任何代码 - 有几种内存使用情况:

  • 二进制代码大小,实际上 -Os 应该优化它
  • 堆内存,使用C dynamic allocation,即malloc;您显然应该知道如何以及分配多少堆内存(以及后来的 free-d)。实际内存消耗将取决于您的特定 malloc 实现(例如,许多实现,当调用 malloc(25) 时实际上可能消耗 32 个字节),而不是编译器。顺便说一句,您可以将您的库设计为使用一些 memory pools 甚至实现您自己的分配器(在 mmap 等操作系统系统调用之上,或在 malloc 等之上...)
  • 局部变量,即调用堆栈上的 call frames。这主要取决于您的代码(但是优化编译器,例如 -Os-O2 for gcc,可能会使用更多的寄存器,并且可能会使用更多的寄存器优化时堆栈更少)。您可以将 -fstack-usage 传递给 gcc 以要求它提供每个调用帧的大小,并且您可以提供 -Wstack-usage=len 以在调用帧超过 len 字节时发出警告。
  • 全局或静态变量。您应该知道它们需要多少内存(您可以使用 nm 或其他一些 binutils 程序来查询它们)。顺便说一句,小心将函数内的某些变量声明为static 会降低堆栈消耗(但您不能对每个变量或每个函数都这样做)。

另请注意,在某些有限情况下,GCC 正在执行 tail calls ,然后堆栈使用率降低(因为调用者的堆栈帧在被调用者中被重用)。 (另请参阅 this old question)。

您还可以要求编译器打包一些特定的 struct-s(注意,这可能会显着降低性能)。您需要使用一些 type attributes,例如 __attribute__((packed)) 等...也许还有一些 variable attributes 等...

也许您应该阅读更多关于 Garbage Collection 的内容,因为 GC 技术、概念和术语可能相关。参见 this answer

如果在 Linux 上,valgrind 工具也应该有用...(在调试阶段,最近的 GCC 的 -fsanitize=address 选项)。

你也可以使用一些 code generation options,比如 -fstack-reuse=-fshort-enums-fpack-struct-fstack-limit-symbol=-fsplit-stack ; 要非常小心:一些这样的选项会使您的二进制代码不兼容您现有的 C(和其他!)库(然后您可能需要重新编译所有使用的库,包括您的 libc ,具有相同的代码生成标志)。

您可能应该通过 link-time optimizations 启用 compiling and linking with -flto(添加其他优化标志,如 -Os)。

您当然应该使用 最新版本的 GCC。请注意,GCC 5.1 已于几天前(2015 年 4 月)发布。

如果您的库足够大,值得付出努力,您甚至可以考虑使用 MELT 自定义 GCC 编译器(以帮助您了解如何减少内存消耗)。这可能需要数周或数月的工作。

关于c - 如何针对内存使用优化 GCC 编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29853981/

相关文章:

c - GCC 链接时间错误 - 没有规则可以制定目标

c++ - undefined reference yaml-cpp

c++ - 是否可以在 Rust 中接收指向 C 函数的指针并将其回调?

c - 在 C 中初始化数组中的元素不会插入到另一个数据结构中

c - Makefile,clang OK,gcc错误

c - 使用 GCC + ARM 减少递归期间的堆栈使用

c++ - std::unique_ptr 在 GCC 中工作,但不会在 Visual Studio 中编译

c - 我如何在父子进程之间共享内存,以便在它们死亡时自动释放内存

c# - Lotus Notes c API 问题

c - 为什么在我运行C代码时显示 “collect2.exe: error: ld returned 1 exit status”错误