博客
关于我
图解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/

    你可能感兴趣的文章
    No fallbackFactory instance of type class com.ruoyi---SpringCloud Alibaba_若依微服务框架改造---工作笔记005
    查看>>
    No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalanc
    查看>>
    No mapping found for HTTP request with URI [/...] in DispatcherServlet with name ...的解决方法
    查看>>
    No mapping found for HTTP request with URI [/logout.do] in DispatcherServlet with name 'springmvc'
    查看>>
    No module named 'crispy_forms'等使用pycharm开发
    查看>>
    No module named cv2
    查看>>
    No module named tensorboard.main在安装tensorboardX的时候遇到的问题
    查看>>
    No module named ‘MySQLdb‘错误解决No module named ‘MySQLdb‘错误解决
    查看>>
    No new migrations found. Your system is up-to-date.
    查看>>
    No qualifying bean of type XXX found for dependency XXX.
    查看>>
    No qualifying bean of type ‘com.netflix.discovery.AbstractDiscoveryClientOptionalArgs<?>‘ available
    查看>>
    No resource identifier found for attribute 'srcCompat' in package的解决办法
    查看>>
    no session found for current thread
    查看>>
    No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
    查看>>
    NO.23 ZenTaoPHP目录结构
    查看>>
    no1
    查看>>
    NO32 网络层次及OSI7层模型--TCP三次握手四次断开--子网划分
    查看>>
    NOAA(美国海洋和大气管理局)气象数据获取与POI点数据获取
    查看>>
    NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
    查看>>
    node exporter完整版
    查看>>