• 为什么要做字节对齐 alignment?


    下面这段 C++ 代码的输出是什么?定义的 Type 占用的字节数(下面简称为字节数)是多少呢?

    #include 
    
    struct Type {
    	char a;
    	int b;
    };
    
    int main(void) {
    	std::cout << sizeof(Type) << '\n';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    经过编译运行,在 x86-64 Linux 机器上输出的结果是 8。如果将成员变量的字节数相加求和,等于 1 + 4 = 5 字节。那多出来的 3 字节做什么了?

    一般,我们会把多出的 3 字节用来做字节对齐。也就引出了文章标题提出的问题:为什么要做字节对齐呢?多占用的字节有什么用处?

    首先,程序加载进内存后,需要将指令、数据读取到 CPU 中;CPU 读取数据的速度要远远超过内存的。为了缓解速度差异,引入了 Cache 机制。

    而在读写 Cache 中的数据时,一般都是按照一定大小来操作的,这个概念被称为 “Cache line”。在因特尔芯片中,一次操作的大小是 64 个字节。假如现在类型 Type 的对象存储在 Cache 的地址分别为 [60, 61, 62, 63, 64]。如果现在 CPU 去读这个对象,你会发现,它正好分布在两个 Cache line 中(分别是 [0,63] 和 [64, 127]),因此要读两次。

    为了尽可能让每次操作都能够访问到完成的数据,而不是分两次进行。编程语言都会引入字节对齐 Alignment 机制(也与 C++ 的处理机制差不多):

    1. 首先,设定每一个基础类型的 alignment 大小,都是 2 的幂。C++ 在 x86-64 Linux 机器上的 alignment 情况如下表(可以通过 alignof(Type) 函数查看):

      类型sizeof(Type)alignof(Type)
      char (unsigned char)11
      short (unsigned short)22
      int (unsigned int)44
      long (unsigned long)88
      float44
      double88
      long double1616
      T*88
    2. 要求某一类型的第一个字节的地址能被 alignment 整除。也就是说,存放 int 值的地址必须是 4 的倍数。

    3. 如果是用户自定义类型,比如文章开头的 struct,它的 alignment 等于 max(所有成员变量的 alignment),也就是 int 类型的 4。

    4. 并且要求 sizeof(Type) 必须是 alignof(Type) 的倍数。

    以 Type 为例,它的成员变量占用字节和为 5,不是 4 的倍数,所以要在 a 后面填充 3 个 byte 空闲字节,将 Type 字节数扩充为 8。你会发现 [8n, 8n+1,…, 8n+7] 总是会在一个 Cache line 里。

    看到这有的朋友可能会问,这个真的一定会确保对象都在一个 Cache line 里吗?

    答案是不能,比如将 Type 改写为下面的形式:

    struct Type {
    	char a;
    	int b;
    	int c;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    首先,通过上面的讲解大家应该都能知道现在 sizeof(Type) == 12,但是 64 不能被 12 整除,也就无法保证对象一定在一次 Cache line 里。

    也就是说,字节对齐只是尽可能减少对象需要 Cache line 的统计学次数。

    关于不同字节数大小的类型,需要的访问 Cache line 预计次数,可以参考这篇文章。你会发现 9 和 12 字节的预计次数竟然是一样的!

    总结

    • 字节对齐的目的是尽可能减少对象需要 Cache line 的统计学次数。
    • 而且,多占用的字节,无法直接访问。
  • 相关阅读:
    Linux系统firewalld防火墙的应用实操(对外端口开放使用,对内端口限制ip地址使用,不使用端口默认关闭)
    QT实现tcp服务器客户端
    CAS核心思想、底层实现
    加油站智能视频监控系统
    CSS 高阶小技巧 - 角向渐变的妙用!
    Security:使用来自 Elastic Security 的端点威胁情报保护主机
    三十一、W5100S/W5500+RP2040树莓派Pico<TCP_Server多路socket>
    diffusion model
    字符串-模板编译
    docker 网络模式 与 ftp 主动模式与被动模式
  • 原文地址:https://blog.csdn.net/Guza_Zh/article/details/133978046