前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >再谈map

再谈map

作者头像
程序员小王
发布2019-05-05 16:35:29
1K0
发布2019-05-05 16:35:29
举报
文章被收录于专栏:架构说架构说

这个文章是对前面 小王职场记 谈谈你的STL理解(1) 修正,仅仅通过测试结果来得出判断和结论 距离 实际还有很大的差距并且还有误区

纳秒基本

1 优缺点

unordered_map:

unordered_map是基于hash_table实现

优点:

Hash表,在数据无冲突 的情况下,插入、查询和删除都可以认为是O(1)的时间复杂度,最完美 常数时间,操作 https://en.wikipedia.org/wiki/Hash_table

缺点:

链地址法冲突的缺点

问题1 哈希表大小设置不合理的,导致频繁扩容,/扩容期间造成内存不足等情况

意思是说:vector扩容期间,回阻塞业务

代码语言:javascript
复制
Redis 通过增量式扩容解决了这个扩容期间业务无法访问的缺点</u>

Redis默认初始化值为4

渐进式哈希`的精髓在于:数据的迁移不是一次性完成的,而是可以通过dictRehash()这个函数分步规划的

代码语言:javascript
复制
在迁移的过程中,数据是在新表还是旧表中并不是一个非常急迫的需求,迁移的过程并不会丢失数据,在旧表中找不到再到新表中寻找就是了(一般情况)

遇到内存不足,然后ha切换 也会有问题。

问题2 如果哈希函数设计不合理,哈希表在极端情况下会变成线性表.性能极低
代码语言:javascript
复制
即使扩容以后他们的位置也不会变化,性能不会发生变化 .

意思是说 :根据 **负载因子** (总键值对数 / 箱子个数) 来调整扩容也无法解决哈希函数设计不*合理的问题

旁白: 负载因子超过某个阈值时,出于链表性能的考虑,会进行Resize的操作
Java :openjdk/jdk/src/share/classes/java/util/HashMap.java

jdk 8 对于链表长度超过 8 的链表将转储为红黑树

image.png

代码语言:javascript
复制
> Redis:经过严格测试,表现良好的默认哈希函数,避免了链表过长的问题,解决了这个缺点

有两个字典,分别存有 100 条数据和 10000 条数据,如果用一个不存在的 key 去查找数据,在哪个字典中速度更快? 这个你不好回答了

红黑树

优点:

能够保证二叉树的插入和查找操作一直都是O(log(n))的时间复杂度(无最坏情况)

The balancing of the tree is not perfect, but it is good enough to allow it to guarantee searching in O(log n) time, where n is the total number of elements in the tree. The insertion and deletion operations, along with the tree rearrangement and recoloring, are also performed in O(log n) time.

https://en.wikipedia.org/wiki/Red%E2%80%93black_tree

Algorithm

Average

Worst case

Space

O(n)

O(n)

Search

O(log n)

O(log n)

Insert

O(log n)

O(log n)

Delete

O(log n)

O(log n)

旁白:理解时间复杂度O(log n)

如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次

image

https://en.wikipedia.org/wiki/Big_O_notation

image.png

优点是占用内存小(没有多余的空节点,不会发生扩容等操作)

旁白:rb tree从众多平衡tree胜出,是因为 功能、性能、空间开销的折中结果,最优。 红黑树相对于AVL树来说,牺牲了部分平衡性以换取插入/删除操作时少量的旋转操作,整体来说性能要优于AVL树(从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长 )

适合频繁更新,删除等操作。

缺点:

  1. 数据查找 根据数据大小有关系。
  2. 随着n的变大(40w),map性能有下降(纳秒级别,相差10倍)也最够满足一般的业务了,

image

  1. 并发性不好

为了解决这些限制,研究人员已经开发了替代结构,例如跳过列表[4],以及可以更加适应并发性的红黑树变种 无锁链接列表和跳过列表

2 黑盒测试(这是错误的分析方式)

代码: https://github.com/wangcy6/weekly/blob/master/reading-notes/unix_nework/code/unordered_map.cpp

2.1 100w随机数据

代码语言:javascript
复制
map insert time: 1421.571000 (1.4秒)
map find time: 557.019000 (0.5秒)
map erase time: 662.265000  (0.6秒,删除需要旋转,因此耗时)

unordered_map insert time: 709.372000 (0.7秒)
unordered_map find time: 258.488000 (0.2秒)
unordered_map erase time: 318.419000 (0.3秒)

2.2 100w有序数据

代码语言:javascript
复制
map insert time: 1133.790000 (1.1秒)
map find time: 770.932000 (0.77增多)
map erase time: 888.817000 (0.88增多)

unordered_map insert time: 357.746000 (0.35秒)
unordered_map find time: 291.077000 (0.29秒 没有发生明显变化)
unordered_map erase time: 331.654000  (0.33秒 没有发生明显变化)

2.3 1千万基本数据

  • 有序数据
代码语言:javascript
复制
map insert time: 12667.974000 (1.1秒-12秒)
map find time: 8834.936000 (0.7秒-8秒)
map erase time: 9612.398000  (0.88秒-9秒)

unordered_map insert time: 4051.746000 (0.35秒-4秒)
unordered_map find time: 2574.762000 (0.29-2.5秒)
unordered_map erase time: 3100.294000(0.33-3秒)
  • 随机数据
代码语言:javascript
复制
map insert time: 21340.048000 (1.4秒-21秒)
map find time: 6861.261000 (0.5秒-6.8秒)
map erase time: 7965.711000 (0.6秒-7.9秒)

unordered_map insert time: 10610.533000 (0.7秒-10.6秒)
unordered_map find time: 3981.091000 (0.2秒-3.9秒)
unordered_map erase time: 4738.190000 (0.3秒4.7秒)

说明: 虽然测试unordered_map性能都好于map .并且没有测试 扩容 切换等情况,因为里面算法不是很清楚。 上面的测试根本没有找到结果

redis测试500w(毫秒级别)

代码语言:javascript
复制
[root@bj02-im-video05 bin]#  ./redis-benchmark -r 5000000 -n 5000000 hset myhash
====== hset myhash ======
  5000000 requests completed in 28.24 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 1 milliseconds
100.00% <= 2 milliseconds
100.00% <= 2 milliseconds
177028.75 requests per second

正确的分析方式:如何解决冲突上

  • 看各自 斜率

纳秒基本

  • 冲突链表的最大长度 来源:http://zhuanlan.51cto.com/art/201709/551395.htm stl::unordered_map :

image.png

gcc4.9.3的哈希算法移植到 ServerFrame::HashMap

image.png

总结

在看这个张图 stl::unordered_map 解释了很多问题

冲突

参考

  1. 几种常见的hash函数 2.https://www.cnblogs.com/me115/p/4975960.html 3.https://stackoverflow.com/questions/11899616/murmurhash-what-is-it
  2. http://en.wikipedia.org/wiki/MurmurHash
  3. http://murmurhash.shorelabs.com/
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Offer多多 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 优缺点
  • unordered_map:
  • 优点:
  • 缺点:
    • 问题1 哈希表大小设置不合理的,导致频繁扩容,/扩容期间造成内存不足等情况
      • 问题2 如果哈希函数设计不合理,哈希表在极端情况下会变成线性表.性能极低
      • 红黑树
      • 优点:
        • 优点是占用内存小(没有多余的空节点,不会发生扩容等操作)
        • 缺点:
        • 2 黑盒测试(这是错误的分析方式)
          • 2.1 100w随机数据
            • 2.2 100w有序数据
              • 2.3 1千万基本数据
                • 正确的分析方式:如何解决冲突上
                  • 总结
                    • 参考
                    相关产品与服务
                    云数据库 Redis
                    腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档