最便宜的解除引用结构?

时间:2015-02-10 15:44:46

标签: c performance data-structures collections memory-layout

我们说我有一个由unsigned int键入的关联数组;值可以是任何固定大小的类型。有一些预先定义的最大数量。实例。

API使用示例:MyStruct * valuePtr = get(1234);put(6789, &myStructInstance); ...基本。

我希望最小化缓存未命中,因为我从这个数组中快速地随机读取条目,所以我预先malloc(sizeof(MyType) * MAX_ENTRIES)以确保参考的位置尽可能。

通用主义对于值数组很重要。我查看了C pseudo-generics,但为了简单起见,我更喜欢void *;但是,不确定这是否与性能目标不一致。最后,我想知道什么是最佳性能。

我应该如何实现关联数组以提高性能?到目前为止的想法......

  • 我是否将关联数组传递给void * ed值数组的单个malloc指针并允许它在内部使用(我们需要保证匹配的键数组大小)?我是否可以这样做,因为类型需要(?)才能知道为了索引值数组?
  • 我是否在关联数组中有一个单独的void * valuePtrs[],然后让这些指针指向malloc ed值数组中的每个元素?这似乎可以避免需要了解具体类型?
  • 我是否使用C pseudo-generics从而允许get()返回特定的值类型?当然,在这种情况下,唯一的好处是不必明确地施放,例如, MyStruct* value = (MyStruct*) get(...) ...数组元素仍然必须被解除引用,因此具有相同的开销吗?

而且,一般来说,上述最小化错误的方法是否有意义?

2 个答案:

答案 0 :(得分:1)

在这两种情况下,性能基本相同。 在第一个(void *实现)中,您需要查找值+取消引用指针。所以这些是两条指令 在另一个实现中,您需要将索引与值的大小相乘。所以这个实现也要求两个指令。 但是,第一个实现将更容易实现。此外,阵列是完全透明的;用户不需要知道数组中的结构类型。

答案 1 :(得分:1)

根据优缺点查看下面分类的解决方案(感谢Ruben协助我的思考)......我已经为我的用例实现了选项2和5,这有点概括;如果您需要非常具体的一次性数据结构,我建议使用选项4。选项3是最灵活的,而对代码来说是微不足道的,也是最慢的。选项4是最快的。选项5有点慢,但阵列大小灵活,易于通用。


关联数组结构指向类型指针数组:

专业不需要失败值,不需要显式强制转换,不需要数组的编译时大小

缺点代价高昂的双重deref,需要通用库代码


关联数组结构包含void *指针数组:

专业人员不需要失败值,没有通用库代码

缺点代价为get()的昂贵双重deref,显式强制转换,如果不使用VLA,则需要编译数组的时间


关联数组结构指向void *值数组:

专业没有通用库代码,不需要数组的编译时大小

缺点昂贵的三重deref,get()之后的显式强制转型,需要偏移计算,这需要明确传递的sizeof值


关联数组结构包含类型值数组:

专业廉价单个deref,不需要显式强制转换,连续分配的键和条目

缺点需要通用库代码,必须提供失败值,如果不使用VLA则需要编译数组的时间


关联数组结构指向类型值数组:

专业不需要显式强制转换,灵活的数组大小

缺点代价高昂的双deref,需要通用库代码,必须提供失败值,如果不使用VLA则需要编译数组的时间