博客
关于我
图解Go语言内存分配
阅读量:452 次
发布时间:2019-03-06

本文共 1552 字,大约阅读时间需要 5 分钟。

Go语言内置运行时(runtime)的内存管理机制

Go语言的内存管理机制是其运行时(runtime)的核心组成部分之一。传统的内存管理方式依赖于系统调用,这在多线程环境下会导致不少问题。Go runtime抛弃传统的内存分配方式,采用了一种自主管理的模式,实现了更高效的内存使用方式,如内存池、预分配等。这种机制避免了频繁的系统调用,提升了性能表现。

内存分配的基本原理

Go runtime在程序启动时,向操作系统申请一块内存区域(称为arena),并将其划分为三个主要区域:

  • 512MB:用于存放TLS(线程本地存储)。
  • 16GB:用于存放堆区(用于动态分配的对象)。
  • 512GB:用于存放程序的静态数据。

堆区管理

堆区是Go运行时用于动态分配的内存区域。heap区被划分为多个8KB的小块,每个小块称为page。这些page被组合成更大的管理单元,称为mspan(memory span)。mspan是一个包含多个连续page的内存块,用于分配多个对象。

每个mspan都有一个对应的记录,存储其起始地址、所包含的page数量、以及分配给对象的块数量。为了实现内存管理的高效,mspan还维护了一个位图,用于标记哪些块已经被分配。

内存管理单元

mspan是Go内存管理的基本单元。它根据对象的大小将内存划分为若干个对象块。每个mspan都有一个规格(Size Class),决定其能分配的最大对象大小。规格的划分非常重要,直接影响垃圾回收的效率。

mspan的规格划分如下:

  • Size Class:决定了mspan分配的最大对象大小。
  • Span Class:与Size Class的关系为Span Class = 2 × Size Class。每个Size Class对应两个Span Class,分别用于存放带有指针和不带指针的对象。

mspan的大小划分非常灵活,支持多种对象大小的分配需求。

内存管理组件

Go runtime中的内存管理由三大组件协同工作:

  • mcache(本地缓存):每个工作线程都有一个mcache,用于本地缓存可用的mspan资源。mcache的结构体包含所有规格大小的mspan,用于快速分配小对象。mcache的大小是NumSpanClasses的两倍,确保能够同时缓存带有指针和不带指针的对象。

  • mcentral(全局管理器):mcentral用于管理所有线程共享的mspan资源。它维护了空闲和已分配的mspan列表,支持线程间的mspan交换。mcentral的操作需要互斥锁,以确保线程安全。

  • mheap(内存池):mheap是Go程序持有的所有堆内存资源。它负责管理未切割的mspan,并向操作系统申请新内存。当mcentral无法满足分配需求时,mheap会申请更多内存。

  • 内存分配流程

    内存分配的流程根据对象的大小分为三个阶段:

  • 小对象(≤16B):这些对象通过mcache的“小分配器”直接分配,无需遍历mspan。

  • 一般对象(16B < size ≤32KB):首先确定对象的规格大小,然后从mcache中获取相应规格的mspan。如果mcache中没有可用mspan,则向mcentral申请。如果mcentral也无可用mspan,则向mheap申请。如果mheap也没有合适的mspan,则向操作系统申请内存。

  • 大对象(>32KB):大对象直接从mheap分配。

  • 总结

    Go语言的内存管理机制通过mcache、mcentral和mheap三大组件,实现了高效的内存分配和管理。其核心思想是能复用一定要复用,通过本地缓存和全局管理器,有效减少了内存碎片和系统调用开销。这一机制在多线程环境下表现尤为出色,为Go语言的高性能提供了坚实基础。

    转载地址:http://hiffz.baihongyu.com/

    你可能感兴趣的文章
    nump模块
    查看>>
    Nutch + solr 这个配合不错哦
    查看>>
    NuttX 构建系统
    查看>>
    NutUI:京东风格的轻量级 Vue 组件库
    查看>>
    NutzCodeInsight 2.0.7 发布,为 nutz-sqltpl 提供友好的 ide 支持
    查看>>
    NutzWk 5.1.5 发布,Java 微服务分布式开发框架
    查看>>
    NUUO网络视频录像机 css_parser.php 任意文件读取漏洞复现
    查看>>
    Nuxt Time 使用指南
    查看>>
    NuxtJS 接口转发详解:Nitro 的用法与注意事项
    查看>>
    NVDIMM原理与应用之四:基于pstore 和 ramoops保存Kernel panic日志
    查看>>
    NVelocity标签使用详解
    查看>>
    NVelocity标签设置缓存的解决方案
    查看>>
    Nvidia Cudatoolkit 与 Conda Cudatoolkit
    查看>>
    NVIDIA GPU 的状态信息输出,由 `nvidia-smi` 命令生成
    查看>>
    nvidia 各种卡
    查看>>
    NVIDIA-cuda-cudnn下载地址
    查看>>
    nvidia-htop 使用教程
    查看>>
    nvidia-smi 参数详解
    查看>>
    Nvidia驱动失效,采用官方的方法重装更快
    查看>>
    nvmw安装node-v4.0.0之后版本的临时解决办法
    查看>>