我有一个包含四个字段的结构体,这些字段的类型来自模板参数:
我知道通常重构结构体字段的内存布局可能会由于缓存考虑而产生性能影响,并且通常这些影响至少与更好的打包潜在收益同样重要。尽管如此,我仍想探索权衡,但在我的情况下,如果不解决这个问题,我无法正确地进行。
template <typename T1, typename T2, typename T3, typename T4>
struct __attribute__((aligned(8))) four_tuple {
typedef struct {
T1 t1;
T2 t2;
T3 t3;
T4 t4;
} payload;
payload p;
};
每种类型 T1
, T2
, T3
, 和 T4
,都保证是一种基本类型或一个 four_tuple<...>::payload
类型。这些保证是递归的 - 您可以将结构视为编码了一个 四叉树,其叶节点是基本类型。
我的目标是让该结构体具有尽可能小的 sizeof
,条件是所有叶节点都得到正确对齐。可用于优化的工具是使用类模板特化:
- 重新排序字段
t1
,t2
,t3
,t4
- 添加填充字段
- 在
payload
上使用 gcc 属性packed
- 可能还有其他方法?
我感觉使用 enable_if
和 SFINAE 可以找到这个问题的巧妙解决方案。有人能找到吗?
using Foo = four_tuple<char,double,char,double>
,我们的有效负载和总大小将为32。如果我们简单地声明有效负载 packed
,那么 double
将不会很好地对齐。一个模板特化,以递减顺序重新排序字段(这里是 double, double, char, char
),将给出24的有效负载和总大小。但它使用的额外6个字节是浪费的,可以通过考虑 using Bar = four_tuple<Foo::payload,int,int,int>
来看到这一点。在最佳包装下,Bar
可以适合32字节,但是使用此方案需要40字节。直接应用字段重新排序与 packed
将导致 Bar
中的 int
不对齐 - 需要一些填充。我知道通常重构结构体字段的内存布局可能会由于缓存考虑而产生性能影响,并且通常这些影响至少与更好的打包潜在收益同样重要。尽管如此,我仍想探索权衡,但在我的情况下,如果不解决这个问题,我无法正确地进行。
char
,那么你想要的大小就是 4,不是吗?这不需要一个 8 的对齐。 - user743382four_tuple<Foo::payload,int,int,int>
可以达到32的大小且不会出现错误对齐。如果您不添加packed
,它将具有40的大小。 - dshin