努力学习go中,看到skoo博客内容很不错, 所以转载学习下

前两天有小伙伴问道是否看过 Go 语言 map 的实现,当时还真没看过,于是就花了一点时间看了一遍 runtime 源码中的 hashmap 实现。map 的底层实现就是一个 hash 表,大体结构上和平时在脑海里的 hash 表差不多,但确实有很多细节(“Devils in the details”)。

hashmap 通过一个 bucket 数组实现,所有元素将被 hash 到数组中的 bucket 中,bucket 填满后,将通过一个 overflow 指针来扩展一个 bucket 出来形成链表,也就是解决冲突问题。这也就是一个基本的 hash 表结构,没什么新奇的东西,下面总结一些细节吧。

  1. 注意一个 bucket 并不是只能存储一个 key/value 对,而是可以存储8个 key/value 对。每个 bucket 由 header 和 data 两部分组成,data 部分的内存大小为:(sizeof(key) + sizeof(value)) * 8,也就是要存储8对 key/value,这8对 key/value 在 data 内存中的存储顺序是:key0key1…key7value0value1…value7,是按照顺序先依次存储8个 key 值,然后存储对应的8个 value。 为什么不是存储为 key0value0…key7value7 呢?主要是方便访问吧。
  2. 如果 key, value 的类型大小超过了128字节,将不会直接存储值,而是存储其指针。
  3. bucket 的 header 部分有一个 uint8 tophash[8] 数组,这个数组将用来存储8个 key 的 hash 值的高8位值。比如:tophash[0] 存储的值就是 hash(key0) » (64 - 8)。保存了一个 key 的 hash 高8位部分,在查找/删除/插入一个 key 的时候,可以先判断两个 key hash 的高8位是否相等,如果不等,那就根本不用去比较 key 的内容。所以这里保存一下 hash 值的高8位可以作为第一步的粗略过滤,不少时候可以省掉比较两个 key 的内容,因为比较两个 key 是否相等的代价远比两个 uint8 的代价高。当然,这里如果存储整个 hash 值,而不仅仅是高8位的话,判断效果将更好,但内存的占用就会多很多了。
  4. bucket 的8个 key/value 空间如果都填满后,就会分配新的 bucket,通过 overflow 指针串联起来。注意这个链表指针被命名为 overflow,代表的正是 bucket 溢出了,这个命名感觉很好,hash 表实现的时候我们应该努力避免 bucket overflow。
  5. hashmap 是会自增长的,也就说随着插入的 kv 对越来越多,初始的 bucket 数组就可以需要增长、重新hash 所有元素,性能才会好。bucket 数组增长的时机就是插入的元素个数大于了bucket数组大小 * 6.5,为什么是6.5,这个在代码注释里有说明,主要是测试出来的经验值。
  6. hashmap 每次增长,都是重新分配一个新的 bucket 数组,新 bucket 数组是之前 bucket 数组的2倍大小。
  7. hashmap 增长后,需要将老 bucket 数组中的元素拷贝到新的 bucket 数组,这个拷贝过程不是一口气立马完成的,而是采用了增量式的拷贝,也就是说分配了新的 bucket 数组后,并没有立刻拷贝元素,而是等接下来每次插入一个元素的时候,才拷贝一点,随着插入的动作增多,逐渐就将全部元素拷贝到了新的 bucket 数组中。
  8. 在 make 一个 map 对象的时候,如果不指定大小的话,bucket 数组默认就是1了,随着插入的元素增多,就会增长成2,4,8,16等。可以看出不指定初始化大小的map,很可能要经历很多次的增长、元素拷贝。我们应该给 map 指定一个合适的大小值。

原文:http://skoo.me/go/2014/06/07/go-map

Go Runtime hashmap实现的更多相关文章

  1. golang: 常用数据类型底层结构分析

    虽然golang是用C实现的,并且被称为下一代的C语言,但是golang跟C的差别还是很大的.它定义了一套很丰富的数据类型及数据结构,这些类型和结构或者是直接映射为C的数据类型,或者是用C struc ...

  2. 【GoLang】golang底层数据类型实现原理

    虽然golang是用C实现的,并且被称为下一代的C语言,但是golang跟C的差别还是很大的.它定义了一套很丰富的数据类型及数据结构,这些类型和结构或者是直接映射为C的数据类型,或者是用C struc ...

  3. Golang 入门 : 映射(map)

    映射是一种数据结构,用于存储一系列无序的键值对,它基于键来存储值.映射的特点是能够基于键快速检索数据.键就像是数组的索引一样,指向与键关联的值.与 C++.Java 等编程语言不同,在 Golang ...

  4. Go语言 map的实现

    Go中的map在底层是用哈希表实现的,你可以在 $GOROOT/src/pkg/runtime/hashmap.goc 找到它的实现. 数据结构 哈希表的数据结构中一些关键的域如下所示: struct ...

  5. 深度解密Go语言之 map

    目录 什么是 map 为什么要用 map map 的底层如何实现 map 内存模型 创建 map 哈希函数 key 定位过程 map 的两种 get 操作 如何进行扩容 map 的遍历 map 的赋值 ...

  6. 你不知道的Golang map

    在开发过程中,map是必不可少的数据结构,在Golang中,使用map或多或少会遇到与其他语言不一样的体验,比如访问不存在的元素会返回其类型的空值.map的大小究竟是多少,为什么会报"can ...

  7. 大话图解golang map

    前言 网上分析golang中map的源码的博客已经非常多了,随便一搜就有,而且也非常详细,所以如果我再来写就有点画蛇添足了(而且我也写不好,手动滑稽).但是我还是要写,略略略,这篇博客的意义在于能从几 ...

  8. golang map实现原理

    这篇文章主要讲 map 的赋值.删除.查询.扩容的具体执行过程,仍然是从底层的角度展开.结合源码,看完本文一定会彻底明白 map 底层原理. 我要说明的是,这里对 map 的基本用法涉及比较少,我相信 ...

  9. Java中hashCode()方法以及HashMap()中hash()方法

    Java的Object类中有一个hashCode()方法: public final native Class<?> getClass(); public native int hashC ...

随机推荐

  1. strictmode

    最新的Android平台中(Android 2.3起),新增加了一个新的类,叫StrictMode(android.os.StrictMode).这个类可以用来帮助开发者改进他们编写的应用,并且提供了 ...

  2. idea控制台输出乱码

    找到安装目录bin下面的idea64.exe.vmoptions,打开后在最后一行增加 -Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeC ...

  3. HDU 1022 Train Problem I 用栈瞎搞

    题目大意:有n辆火车,按一定的顺序进站(第一个字符串顺序),问是否能按规定的顺序出站(按第二个字符串的顺序出去),如果能输出每辆火车进出站的过程. 题目思路:栈的特点是先进后出,和题意类似,还有有一种 ...

  4. phpStudy环境配置多个站点,绑定域名

    经常做网站的朋友,往往要在自已的电脑同时建立多个站点,而phpstudy这款软件就能很好的解决这个问题,大家看下图 点击上图中的 其它选项菜单 ,就会弹出下面的对话框,然后点击 站点域名管理 然 后在 ...

  5. PHP缓存技术的多种方法小结

    这里所说的数据缓存是指数据库查询PHP缓存机制,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件中,以后同样的查询结果就直接从缓 ...

  6. MVVM 入门介绍

    转载自:http://www.objccn.io/issue-13-1/ 我于 2011 年在 500px 找到自己的第一份 iOS 开发工作.虽然我已经在大学里做了好几年 iOS 外包开发,但这才是 ...

  7. android 中ImageButton按下改变背景图片的效果

    最近在做一个app的登陆界面,才发现原来认为很简单的UI效果,其实背后却蕴含的知识很多,积累一个算一个吧. 实现方法有两种:一种是添加代码,一种是配置xml文件. 方法一:代码添加 ImageButt ...

  8. 以图搜图(一):Python实现dHash算法(转)

    近期研究了一下以图搜图这个炫酷的东西.百度和谷歌都有提供以图搜图的功能,有兴趣可以找一下.当然,不是很深入.深入的话,得运用到深度学习这货.Python深度学习当然不在话下. 这个功能最核心的东西就是 ...

  9. Win7下配置Django+Apache+mod_wsgi+Sqlite

    搭建环境: win7 64位 Django 1.8.5 Apache2.4.17 mod_wsgi_ap24py27.so Python2.7.9 1 安装Apache 下载Apache Haus版, ...

  10. jq的合成事件

    jq中有两个合成事件 hover()和toggle() 1.hover() hover方法用于模拟光标悬停事件.当光标移动到元素上时,会触发指定的第一个函数(enter),当光标移出这个元素时,会触发 ...