将应用程序从32位升级到64位会增加指针大小和对象的内存占用。
我正在寻找尽可能减少对象内存占用的方法。对于POD结构体,我会转储结构体的内存布局,以确定如何打包成员并减少编译器填充。
是否有一种方法可以了解非POD对象(如类实例)的内存布局?如何实现类对象的打包类似的操作?
谢谢, 丹
将应用程序从32位升级到64位会增加指针大小和对象的内存占用。
我正在寻找尽可能减少对象内存占用的方法。对于POD结构体,我会转储结构体的内存布局,以确定如何打包成员并减少编译器填充。
是否有一种方法可以了解非POD对象(如类实例)的内存布局?如何实现类对象的打包类似的操作?
谢谢, 丹
-Wpadded
选项来指示哪些地方添加了填充,然后根据这些信息进行重新排序,在某些情况下可以减小大小。我不知道特定的非 POD 对象数据(即 vtable),尽管我认为这由指针大小所决定。
无论如何,您可以通过编译器指令 #pragma pack
来控制成员的对齐方式,该指令被 GCC 和 Visual Studio 支持。
您还可以阅读美妙的 Agner Fog C++ optimize guide 第 7.18 段:
类或结构体的数据成员在创建类或结构体实例时以声明的顺序依次存储。将数据组织成类或结构体不会产生性能损失。访问类或结构体对象的数据成员所需的时间与访问简单变量所需的时间相同。大多数编译器将对齐数据成员以优化访问以获得更好的性能。
确定类对象的大小:http://www.cprogramming.com/tutorial/size_of_class_object.html
内存布局:http://www.phpcompiler.org/articles/virtualinheritance.html
cl -d1reportAllClassLayout main.cpp
经验法则:从大到小排列;这样可以在元素大小为2的幂时实现完美对齐,否则可以进行手动优化。
请注意,即使CPU能够从违规中恢复过来,适当的对齐通常对速度至关重要。虽然x86和(据我所知)x64 CPU会通过第二次读取来处理不对齐的访问,但由于浪费在不对齐读取上的时间通常比由于较小的工作集而节省的时间要多得多。因此,只有在对多个CPU运行比较时才会“紧密打包”。
对于非POD类型,您需要检查sizeof(element)
。
(如果有大量对象,我可能会使用简单的解析器生成C++代码以转储这些大小)
或者,PVS-Studio分析了结构体大小并提供了重新排序建议。我还没有考虑过它们,但您可以使用评估来确定它是否适合您。