我正在寻找具有以下目标的理想数据容器:
容器的行为必须类似于Queue,具有以下规范:
1)随机访问不是必须的 2)在两个方向上迭代对象必须超快(连续数据会更好)我知道双链表不是高性能容器。 向量(比如c ++中的std :: vector)是好的,但它并没有真正优化从前面删除,我也不认为给定对象大小的矢量化是可能的。
我也在考虑Slot-Map容器的可能性,但不确定它是否是最好的选择。
我想知道是否有更好的选择?
答案 0 :(得分:1)
如果我们真的关心性能,容器不应该动态分配任何内存,即我们应该定义容器中对象的上限。
接口要求确实是排队的,因此看起来最快的选项是指向对象的指针的循环队列。所以容器应该剃掉以下字段:
OBJECT * ptrs[SIZE]
- 固定大小的指针数组。当然,我们会在这里浪费SIZE * sizeof (OBJECT *)
个字节,但从表现来看,它可能是一个很好的交易。size_t head_idx
- 头对象索引。size_t tail_idx
- 尾对象索引。在两个方向上迭代对象必须超快
下一个对象是ptrs[]
中的下一个索引:
if (cur_idx >= head_idx) return nullptr;
return ptrs[(cur_idx++) % SIZE]; // make sure SIZE is a power of 2 constant
Prev对象是ptrs[]
:
if (cur_idx <= tail_idx) return nullptr;
return ptrs[(cur_idx--) % SIZE]; // make sure SIZE is a power of 2 constant
从列表前面执行高性能删除并在后面插入是必须的
pop_front()就像:
一样简单if (tail_idx == head_idx) ... // should not happen, through an error
head_idx++;
push_back()就像:
一样简单if (tail_idx - head_idx >= SIZE) ... // should not happen, through an error
ptrs[(tail_idx++) % SIZE] = obj_ptr; // make sure SIZE if a power of 2 constant
项目不是基本类型,它们是对象
最通用的解决方案是简单地将指针存储在循环队列中,因此对象的大小无关紧要,而且只浪费SIZE次指针,而不是SIZE次对象。但是可以肯定的是,如果你能负担得起预先分配数千个物体,它应该更快......
这些是基于您的性能要求的猜测。我不确定你是否有能力为表现换取一些记忆,所以如果不是这样我很抱歉...
答案 1 :(得分:1)
您可以通过常规vector
和start
索引来告诉您&#34;真实&#34;数据的开头是。
start
。i
,请使用vector[start + i]
。start
重置为零。优点:
缺点:
无论你做什么,都要考虑与自然方法进行比较:记住头部和尾部的双重链表。
是的,这些项目在内存中不会是连续的,因此可能会有更多的缓存未命中;但是,您可以通过偶尔进行碎片整理来解决这个问题:
根据删除/插入/遍历的模式,这可能是可行的。