为了使它具体化,我只想知道为什么在我的64位mac上,Swift编译器说某些类型如Float80
的对齐是16。
要检查类型的内存对齐要求,我使用alignof
函数。
sizeof(Float80) // ~> 16 bytes, it only needs 10 bytes, but because of hardware design decisions it has to be a power of 2
strideof(Float80) // ~> 16 bytes, clear because it is exact on a power of 2, struct types with Float80 in it, can be bigger
alignof(Float80) // ~> 16 bytes, why not 8 bytes, like String ?
我理解类型的内存对齐小于或等于单词的大小是有益的。
sizeof(String) // ~> 24 bytes, clear because 24 is multiple of 8
strideof(String) // ~> 24 bytes, clear because 24 is multiple of 8
alignof(String) // ~> 8 bytes, clear because something greater or equal to 8 bytes should align to 8 bytes
许多具有更大内存大小的类型(如String
(大小为24))的内存对齐要求为8个字节。我希望这是我正在使用的CPU / RAM总线的大小,因为我有一个64位的mac和os。
我检查了类型的大小,没有使用sizeof
函数的最后一个填充,并且使用strideof
函数添加填充到结尾(strideof在结构数组中更有用,Swift然后将字节添加到末尾以达到对齐要求的下一个倍数。)
据我所知,填充对于小于或等于8字节大小的类型是必要的。
但我不明白为什么在我的64位mac上有一个大于8字节的内存对齐要求是有利的。
Float80的值需要80位,即10个字节,有6个填充字节。
这是一张图片,使其更加清晰,我的意思。 Float80允许绿色位置,红色位置不允许。 此图片中的内存为8字节块。
答案 0 :(得分:6)
所有“原始数据类型”(该术语可能是错误的,我的意思是 处理器使用的数据类型具有“自然边界”, 并且编译器会相应地将它们对齐在内存中。对齐 取决于处理器(例如x86或ARM)和编程环境(例如32位与64位)。 某些处理器允许未对齐的数据(可能以较低的速度), 有些人不允许这样做。
对于64位Intel架构,要求列于 Data Alignment when Migrating to 64-Bit Intel® Architecture:
然而,64位环境对数据项提出了更严格的要求。未对齐的对象会导致程序异常 [...]
- 在任意地址对齐8位数据
- 将16位数据对齐以包含在对齐的四字节字中
- 对齐32位数据,使其基址为四的倍数
- 对齐64位数据,使其基址为8的倍数
- 对齐80位数据,使其基址为16的倍数
- 对齐128位数据,使其基址为16的倍数
因此,对齐不一定等于“字大小”,它可以是
少或多或少。 Float80
对应于“扩展精度”
x86处理器的浮点类型,它的对齐方式是
需要是16个字节。
C struct
等复合类型在内存中布局
每个成员都在其自然边界上(并插入填充
在必要时间。结构的对齐方式
本身是每个成员的最大对齐方式。
Swift Struct
的内存布局没有正式记录(据我所知)但它可能与C struct
类似。
这是一个简单的例子:
struct AStruct {
var a = Int32(0)
var b = Int8(0)
var c = Int16(0)
var d = Int8(0)
}
println(sizeof(AStruct)) // 9
println(alignof(AStruct)) // 4
println(strideof(AStruct)) // 12
内存布局(可能)是(* =填充):
aaaab*ccd
此处对齐为4,因为这是Int32
所需的对齐方式。结构占用9个字节,但“步幅”为12:
这保证了在结构数组中所有元素都满足
相同的路线。
(请注意,Swift strideOf()
对应于C sizeof()
函数,https://devforums.apple.com/message/1086107#1086107中对此进行了解释。)
Swift字符串的声明显示为
struct String {
init()
}
但我们凡人都看不到实际成员。 在调试器中,它看起来像这样:
表示其成员是指针,
无符号字和另一个指针。所有这些类型都有一个大小和
在64位上对齐8个字节。这可以解释大小(24字节)
和struct Swift
的对齐(8个字节)。
答案 1 :(得分:3)
在Martin R的链接的帮助下,暗示这是处理器设计的决定。我找到了readon为什么。
缓存行。
缓存行是处理器的一个非常小的内存,在我的Intel Mac 64位上它是128位(16字节)。
如问题图片所示,我知道点线和粗线之间存在差异。粗线位于处理器的高速缓存行之间。如果你可以用更多的内存成本做得更好,你不想加载2个缓存行。因此,如果处理器只允许,那么大小为8字节(或更大)的类型在高速缓存行的开头(16的每个倍数)上对齐。对于与高速缓存行一样大的类型,将不会有两个高速缓存行读取(在我的情况下,字大小加倍,16个字节)。正如您在图片中看到的那样,只有红色块穿过粗线(因此每个设计不允许使用它们)。
请参阅附带的链接以获取更多信息。