合理布局结构体,精打细算 cacheline

突然想起多年前做的一个优化,相关的还涉及一个诡异的事,先看这两篇文字:保持内存紧凑性快速路径慎用 kmalloc

最近又遇到这类事,还是一样的原则,“一起经常被访问的字段要紧挨着放,尽量使它们处于同一个 cacheline”。看一个紧凑型的结构体:

#define CACHELINE_SIZE 128
#define ARRAY_SIZE 100000

typedef struct {
    int a;
    int b;
    int c;
    int d;
    //char pad[256 - 16];
    char pad2[519 - 16];
} __attribute__((packed)) CompactStruct;

再看一个非紧凑型的:

#define CACHELINE_SIZE 128
#define ARRAY_SIZE 100000

typedef struct {
    int a;
    char padding1[CACHELINE_SIZE - sizeof(int) + 1];
    int b;
    char padding2[CACHELINE_SIZE - sizeof(int) + 1];
    int c;
    char padding3[CACHELINE_SIZE - sizeof(int) + 1];
    int d;
    char padding4[CACHELINE_SIZE - sizeof(int) + 1];
    char pad2[3];
} __attribute__((packed)) ScatteredStruct;

执行下面的逻辑,哪个更快呢:

for (int i = 0; i < ARRAY_SIZE; i++) {
    sum += arr[i].a + arr[i].b + arr[i].c + arr[i].d;
}

结构体字段的布局也是门手艺。像 TCP 处理,比如在接收路径,会频繁访问 snd_cwnd,snd_una,snd_wnd,snd_nxt,…,那么就有必要让上述这些字段挨得近一些,而不是随意散布在结构体的任意位置。总之,这个优化是立竿见影的。

但这种优化是极度拧巴的体系结构相关,我就从公司的 x86_64 换到家里的 Apple M2,结构体宏定义就改了一大堆,站在程序的视角,它本不应该了解这么多东西,cache 是默默起作用的,但反过来,既然你想让 cache 起更大作用,那就必须理解它的细节,方能调教好它。

但要记住,这类优化措施一定是最后才要考虑的,远在算法优化和系统级优化之后,首先还是要考虑算法能不能更优,压缩大 O 数量级,其次要考虑系统能不能更优,比如锁,并行,再然后就是操作系统级别的,比如进程,线程,最后才是体系结构相关的优化,这也是一个自上而下的顺序,从你要解决问题的算法开始,到硬件结束。

浙江温州皮鞋湿,下雨进水不会胖。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值