我们说我有一个由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值数组中的每个元素?这似乎可以避免需要了解具体类型?get()
返回特定的值类型?当然,在这种情况下,唯一的好处是不必明确地施放,例如, MyStruct* value = (MyStruct*) get(...)
...数组元素仍然必须被解除引用,因此具有相同的开销吗?而且,一般来说,上述最小化错误的方法是否有意义?
答案 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则需要编译数组的时间