stl中unordered_map的insert/clear 性能问题解决

最近项目中使用到stl unordermap,当map存储的key数量上升到10的6次-7次甚至8次以上时,unordermap的insert接口性能有严重瓶颈

下面是测试代码:

int main() {
    std::unordered_map t;
    for (int i = 0; i <= 10000000; ++i) {
    t.insert(make_pair(i, 1));
    }
}
以上 运行时间

real    0m5.231s
user    0m4.888s
sys     0m0.331s

原因是随着插入元素增多,insert过程中发生了碰撞,碰撞开链到一定的阈值,触发了增加bucket,进而触发了rehash,打印bucket_size可以看到bucketsize一直在增加,代价非常大

unorderedmap提供了reserve和rehash两个接口

reserve可以用来预留元素个数,rehash根据提供的元素个数预留足够的bucket数目

修改后代码

int main() {
    std::unordered_map t;
    t.reserve(10000000);
    t.rehash(10000000);
    for (int i = 0; i <= 10000000; ++i) {
        t.insert(make_pair(i, 1));
    }
}

运行时间如下:

real    0m3.823s
user    0m3.551s
sys     0m0.262s

有很大的好转。

另外,map大了,带来的问题就是clear非常耗时,上面的map clear一次,大约在300ms

将clear换成如下代码:

std::unordered_map tmp;
t.swap(tmp);

时间马上降到微秒级别

Exchanges the contents of the container with those of other. Does not invoke any move, copy, or swap operations on individual elements
上面是对swap的说明

swap的时间复杂度是常数,根据说明,可以看出应该是底层内存指针的交换

Removes all elements from the container.
Invalidates any references, pointers, or iterators referring to contained elements. May also invalidate past-the-end iterators.
上面是对clear的说明,可以看出其时间复杂度是线性的,随元素个数变化,个数多了,挨个销毁,自然就慢了


以上。



你可能感兴趣的:(c++)