C++ “影响有多大?”;“包装”;结构对性能的影响
我的目标不是开始微优化,所以如果这就是我的目标,我很乐意放弃这个问题。但我将要开始做一些设计决策,希望了解更多信息 我正在阅读和处理一种文件格式,其中包含许多以定义良好的格式记录的数据结构。我在代码中将它们表示为结构 现在,如果我用C++ “影响有多大?”;“包装”;结构对性能的影响,c++,performance,C++,Performance,我的目标不是开始微优化,所以如果这就是我的目标,我很乐意放弃这个问题。但我将要开始做一些设计决策,希望了解更多信息 我正在阅读和处理一种文件格式,其中包含许多以定义良好的格式记录的数据结构。我在代码中将它们表示为结构 现在,如果我用#pragma pack(1)将结构打包成一个1字节的对齐方式,我就可以直接从IO流读取结构到结构指针。这很方便。如果我不打包结构,我可以一个接一个地fread字段,或者一次fread块,然后一个接一个地重新解释结构字段,这可能会很快变老 作为参考,结构将被成千上万的
#pragma pack(1)
将结构打包成一个1字节的对齐方式,我就可以直接从IO流读取结构到结构指针。这很方便。如果我不打包结构,我可以一个接一个地fread
字段,或者一次fread
块,然后一个接一个地重新解释结构字段,这可能会很快变老
作为参考,结构将被成千上万的人(可能)读取,并可能对其进行一些数字运算。它们主要由无符号16位整数(约60%)、无符号32位整数(约30%)和一些64位整数组成
所以现在的问题是,我是否
- 执行数以万计的小电话
fread
- 读取块并复制相关字节
- 打包结构并直接读取它们
如果需要不同于源的endianness,可以对结构的每个元素调用函数来分别修复它们。在这一点上,直接读取的简单性和清晰性将会降低,您可能会更好地使用另一种方法。根据您对另一个答案的评论,您的代码将不受平台影响,并且文件格式的endian特性已明确指定。在这种情况下,直接读入压缩的
结构
会失去很多清晰度,因为它需要一个读取后的尾端清理步骤,否则会在尾端与文件格式不同的体系结构上产生不正确的数据
假设您总是知道字节数(可能来自文件中的结构类型指示符),我建议使用工厂模式,其中创建的对象的构造函数知道如何逐个属性从内存缓冲区中提取字节(如果文件足够小,您可以将整个内容读入缓冲区,然后通过构造函数执行循环/工厂创建/反序列化到对象中。这样,您可以控制尾数并允许编译器所需的结构对齐。最终,解决方案a和解决方案B之间的性能差异只能由解决方案B确定。)在互联网上提问会给你带来不同的结果,这些结果可能反映你的情况,也可能不反映你的实际情况 当您“未对齐”数据时,处理器需要对一段数据执行多次读取[这同样适用于写入]。具体需要多少额外时间取决于处理器-一些处理器不会自动执行,因此运行时系统将捕获“错误读取”,并在某个仿真层中执行读取[或者,在某些处理器中,只是为了“未对齐的内存访问”而终止进程]。显然,采取陷阱并执行两个读取操作,然后返回调用代码对性能有着非常重要的影响——它很容易比对齐的读取操作花费数百个周期 在x86的情况下,它“工作方式与您预期的一样”,但通常会额外增加1个时钟周期[假设数据已经在一级缓存中]。在现代处理器中,一个时钟周期不是很长,但是如果循环的迭代次数为100000000000次,并且读取未对齐的数据n次,那么您现在在执行时间中添加了n*100000000000个时钟周期,这可能非常重要 其他替代方案也会对性能产生影响。执行大量小读取可能比执行一次大读取慢得多。从性能角度来看,转换函数可能更好 再次强调,请不要将此视为“给定的”,您确实需要比较不同的解决方案(或者选择一个,如果性能不差,代码看起来也不可怕,那么就到此为止)。我确信,您可以找到您建议的三个“最佳”解决方案中每一个的案例
还要记住,#
pragma pack
是特定于编译器的,要实现允许您在“Microsoft”和“gcc”之间进行选择的宏并不容易例如,解决方案。编辑:似乎较新的gcc版本确实支持此选项,但并非所有编译器都支持此选项。唯一正确的答案是:对其进行基准测试。我认为您的代码很可能是IO绑定的,打包或不打包对性能的影响是不可测量的,但如果没有基准测试,这只是猜测。它也非常依赖于您的平台。某些平台甚至不接受未对齐的读/写操作,因此您甚至没有机会打包您的结构。如果您的代码是cr