针对大型复杂map的GC优化, 变成map[uint64]int+外部二级索引切片 大幅减少GC耗时

yudeguang · · 885 次点击 · 开始浏览    置顶

# noGCMapIndex 对于大型map,比如总数达到千万级别的map,如果键或者值中包含引用类型(string类型,结构体类型,或者任何基本类型+指针的定义 *int, *float 等),那么这个MAP在垃圾回收的时候就会非常慢,GC的周期回收时间可以达到秒级。 所以对于这种map需要进行优化,把复杂的不利于GC的复杂map转化为基础类型的 map[uint64]int+外部二级索引切片的形式。比如 map[string]intercace{} 转换为 map[uint64]int+[]intercace{}的形式,变成这种形式之后,整个gc基本就不耗时了。 注意,这种做法主要适用于单次加载完后,键值对不再变化的情况。对于键值对在运行过程中还要动态增减的情况则不适合。 ```go package main import ( "github.com/yudeguang/noGCMapIndex" "log" "strconv" ) func main() { log.SetFlags(log.Lshortfile | log.Ltime) tstring() tint() } func tstring() { //旧MAP type col struct { a string b string c int } oldMap := make(map[string]col) for i := 0; i < 10; i++ { oldMap[strconv.Itoa(i)] = col{strconv.Itoa(i), strconv.Itoa(i), i} } //旧MAP转换为新形式的map+二级索引切片的形式 data := make([]col, len(oldMap)) m := noGCMapIndex.NewString(len(oldMap)) for k, v := range oldMap { index := m.CreateIndex(k) data[index] = v } //查询数据 key := "3" index := m.GetIndex(key) if index != -1 { log.Println("key:", key, "对应的值为:", data[index]) } else { log.Println(key, "不存在") } } func tint() { //旧MAP type col struct { a string b string c int } oldMap := make(map[int]col) for i := 0; i < 10; i++ { oldMap[i] = col{strconv.Itoa(i), strconv.Itoa(i), i} } //旧MAP转换为新形式的map+二级索引切片的形式 data := make([]col, len(oldMap)) m := noGCMapIndex.NewInt(len(oldMap)) for k, v := range oldMap { index := m.CreateIndex(k) data[index] = v } //查询数据 key := 3 index := m.GetIndex(key) if index != -1 { log.Println("key:", key, "对应的值为:", data[index]) } else { log.Println(key, "不存在") } } ```

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

885 次点击  
加入收藏 微博
4 回复  |  直到 2022-07-20 11:31:32
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传