3

我想计算/总结由于打包导致的目标文件中的开销(理想情况下,让 gcc 为我最小化它)。

例如,考虑以下结构(32 位 x86,gcc):

struct a { 
    uint8_t a_char;
    uint32_t an_integer
    uint8_t another_letter;
};

虽然实际数据只占用 6 个字节,但该结构在内存中占用 12 个字节,因为这两个字符后跟 3 个填充字节。通过重新排序结构如下:

struct b { 
    uint32_t an_integer
    uint8_t a_char;
    uint8_t another_letter;
};

该结构将只有 sizeof(struct b) == 8 (仍然是 4 字节的开销)。

(1) 理想情况下,我希望 gcc 重新排列struct astruct b节省空间,但我的版本 (4.2) 似乎没有针对任何优化级别执行此操作。

(2)或者,给定struct a,我想(自动)获得数字6(总开销)或4(最小的开销,如果成员被“理想地”订购)。这样做的目的是确定手动重新排序结构是否值得花时间(可能不值得)。

gcc 有没有办法做(1),有没有可以执行(2)的工具?对于(1),我能想到的最接近的事情是#pragma pack(1),但是(我猜)它会通过使大多数/所有内存访问不对齐而产生严重的性能影响。对于(2),我认为解析调试符号的 Perl 脚本可能能够做到这一点,但我对 DWARF 不够熟悉,无法确定。

4

3 回答 3

8

对于 #1,未完成的原因是 C 和 C++ 标准都禁止结构成员重新排序。

是的,结构打包通常会降低性能。而且,正如评论中提到的,在某些情况下,在非 x86 架构上,如果您尝试对成员进行操作,您可以获得 SIGBUS。

对于#2,是的,一个 perl 脚本可能能够做到这一点。除了解析 DWARF 信息,您可以尝试扫描源代码中的结构定义,并可能生成一些小型测试程序来检查结构和成员的 sizeof() 等等。

于 2011-07-12T07:05:30.253 回答
3

在 linux 中有一个名为 pahole 的工具,它将解析一个带有调试信息的 ELF 文件,并为每个结构打印输出每个成员的对齐方式以及编译器完成了多少填充。如果您发现开销过多,您可以使用该信息来指导您手动打包。

于 2011-07-12T07:42:24.977 回答
0

这不能总是做到,问题是在所有架构上都不允许访问未对齐的内存。这也简化了编译器的一些代码,允许优化对内存本身的某些访问。此外,重组结构可能不值得您花时间,因为每个结构 4-8 字节的开销并不是什么大问题,除非您正在运行对内存非常敏感的软件。至于您的问题,我不确定是否有办法,但我确定是否有人知道他们会让您知道(也许具有最高优化标志的 gcc-4.6 可以吗?)

于 2011-07-12T07:04:22.623 回答