我有一个名为log的结构,里面有13个字符。在做了sizeof(log)之后,我看到大小不是13而是16.我可以使用__attribute __((packed))将它的实际大小设置为13但是我想知道这是否会影响程序的性能。这是一种经常使用的结构。
我希望能够读取结构的大小(13而不是16)。我可以使用宏,但如果这个结构被更改,即添加或删除字段,我希望更新新的大小而不更改宏,因为我认为这很容易出错。有什么建议吗?
答案 0 :(得分:15)
是的,它会影响程序的性能。添加填充意味着编译器可以使用整数加载指令从内存中读取内容。如果没有填充,编译器必须单独加载内容并进行位移以获取整个值。 (即使它是x86,这是由硬件完成的,仍然需要完成)。
考虑一下:如果出于性能原因,编译器为什么会插入随机的,未使用的空间?
答案 1 :(得分:6)
请勿使用__attribute__((packed))
。如果数据结构在内存中,则允许它占用编译器确定的自然大小。如果是用于读取/写入磁盘,则编写序列化和反序列化函数;不要简单地在磁盘上存储cpu-native二进制结构。 “打包”结构确实有没有合法用途(或者很少;请参阅对此答案的评论,以了解可能存在不同意见的观点)。
答案 2 :(得分:5)
是的,它会影响性能。在这种情况下,如果使用((packed))
属性分配此类结构的数组,则大多数结构必须最终未对齐(而如果使用默认包装,则它们都可以在16字节边界上对齐)。如果它们对齐,那么复制这些结构会更快。
答案 3 :(得分:5)
是的,它会影响性能。具体取决于它是什么以及如何使用它。
未对齐的变量可能跨越两个缓存行。例如,如果你有64字节的高速缓存行,并且你从一个13字节结构的数组中读取一个4字节的变量,那么它将有四分之三(4.6%)的可能性分布在两行中。额外缓存访问的代价非常小。如果你的程序所做的一切都是在那一个变量上,那么4.6%将是性能命中的上限。如果日志记录占程序工作量的20%,并且读取/写入该结构的日志记录占50%,那么您已经只占了一小部分。
另一方面,假设需要保存日志,将每个记录缩小3个字节可节省19%,这相当于大量内存或磁盘空间。主内存,尤其是磁盘速度很慢,因此您可能最好将日志打包以减小其大小。
至于阅读结构的大小而不用担心结构变化,请使用sizeof
。但是,您喜欢使用数字常量,const int
,enum
或#define
,只需添加sizeof
。
答案 4 :(得分:-1)
与所有其他性能优化一样,您需要对代码进行概要分析以找到正确的答案。正确的答案因架构而异 - 以及您如何使用您的结构。
如果你正在创建巨大的阵列,那么打包所节省的空间可能意味着拟合和不适合缓存之间的差异。或者您的数据可能已经适合您的缓存,在这种情况下,它将没有任何区别。如果你在一个STL关联容器中分配大量的结构,为你的结构分配operator new
的存储,它可能根本不重要 - operator new
可能会将你的存储空间扩展到某个地方无论如何对齐。
如果您的大多数结构都存在于堆栈中,则无论如何都可能已经优化了额外的存储空间。
对于这个简单的测试,我建议建立一个计时器,然后尝试两种方式。为了进一步优化,我建议使用分析器来识别您的瓶颈并从那里开始。