前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 内存管理 -- 内存分配 一

Go 内存管理 -- 内存分配 一

作者头像
邹志全
发布2019-07-31 11:19:07
1.3K0
发布2019-07-31 11:19:07
举报
文章被收录于专栏:EffectiveCodingEffectiveCoding
前言

go作为一个比较新晚(新)的语言,自然借鉴前辈们的优点,比如说语言本身负责内存管理、对协程和高并发的高优支持、简单高效的语法等。本篇及后续的几篇要讲的就是还没提到的比较复杂的内存管理。 学习内存管理(分配&回收)前,如果有JVM的内存管理的基础,会变得非常简单,如果是第一次接触内存管理,在看完Go的内存管理后可以去看看JVM的,对比着学习比较容易理解。 go的内存管理思路是基于google 的tcmalloc(thread-caching-malloc)实现的,常见的内存分配器还有ptmalloc、jemalloc,但是tcmalloc的性能更高,尤其是高并发场景下。

关于tcmalloc

tcmalloc的分配的内存主要来源于:全局缓存堆进程私有缓存,小容量的内存申请使用私有缓存,如果私有缓存不够,则从全局缓存堆中申请一部分作为私有缓存。大对象会直接从全局缓存中申请,至于大小的分界是32k。

小对象分配

小对象内存分配默认会分配86个不同大小的块,这些块的大小不一致,内部采用单链表数组来组织内存,使用时遵循懒加载策略,等到使用时才进行初始化。

image.png

大对象分配

大于32k的内存申请,属于大对象的分配,使用全局缓存堆直接分配,内存的组织方式也是通过单链表数组进行的,数据长度是256,每个链表的元素的大小是不同的,但都是4k(1page)的整数倍。

image.png

Span

tcmalloc使用span来管理内存分页,一个span可以包含几个连续分页。span的状态只有未分配、作为大对象分配、作为小对象分配。

go内存分配
主流程

1、申请一块较大的虚拟内存空间,用于内存分配及管理 当空间不足时,向系统申请一块较大的内存,如100KB或者1MB 申请到的内存块按特定的size,被分割成多种小块内存(go:_NumSizeClasses = 67),并用链表管理。创建对象时,按照对象大小,从空闲链表中查找到最适合的内存块。 2、销毁对象时,将对应的内存块返还空闲链表中以复用。 3、空闲内存达到最大值时,返还操作系统。

管理组件

go将内存分为三个层级,协程私有内存,全局内存,整体内存叶管理,也因此有这三个层级的内存管理工具。

image.png

mspan: mspan并不直接拥有内存空间,它负责管理起始地址为startAddr、级别(预分配页的个数)为sizeclass的连续地址空间。 mcache: Per-P私有cache,用于实现无锁的object分配,每个mcache有大小为67的mspan数组,存储不同级别大小的mspan。 mcentral: 全局内存,为各个cache提供按大小划分好的mspan,mcentral有个关键方法cacheSpan(),它是整个分配的核心算法 mheap 是真实拥有虚拟地址的结构,page管理,内存不足时向系统申请。 总体来说,他们之间的关系是这样的: Golang程序启动时申请一大块内存,并划分成spans、bitmap、arena区域,arena区域按页划分成一个个小块,span管理一个或多个页,mcentral管理多个span供线程申请使用,mcache作为线程私有资源,资源来源于mcentral。 本篇暂时就介绍这么多。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.07.15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 关于tcmalloc
    • 小对象分配
      • 大对象分配
        • Span
        • go内存分配
          • 主流程
            • 管理组件
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档