go语言动态生成大块内存 go动态编译

Golang 1.14中内存分配、清扫和内存回收 Golang的内存分配是由golang runtime完成,其内存分配方案借鉴自tcmalloc 。
主要特点就是
本文中的element指一定大小的内存块是内存分配的概念,并为出现在golang runtime源码中
本文讲述x8664架构下的内存分配
Golang 内存分配有下面几个主要结构
Tiny对象是指内存尺寸小于16B的对象 , 这类对象的分配使用mcache的tiny区域进行分配 。当tiny区域空间耗尽时刻,它会从mcache.alloc[tinySpanClass]指向的mspan中找到空闲的区域 。当然如果mcache中span空间也耗尽 , 它会触发从mcentral补充mspan到mcache的流程 。
小对象是指对象尺寸在(16B,32KB]之间的对象,这类对象的分配原则是:
1、首先根据对象尺寸将对象归为某个SpanClass上,这个SpanClass上所有的element都是一个统一的尺寸 。
2、从mcache.alloc[SpanClass]找到mspan,看看有无空闲的element,如果有分配成功 。如果没有继续 。
3、从mcentral.allocSpan[SpanClass]的nonempty和emtpy中找到合适的mspan , 返回给mcache 。如果没有找到就进入mcentral.grow()—mheap.alloc()分配新的mspan给mcentral 。
大对象指尺寸超出32KB的对象 , 此时直接从mheap中分配,不会走mcache和mcentral,直接走mheap.alloc()分配一个SpanClass==0 的mspan表示这部分分配空间 。
对于程序分配常用的tiny和小对象的分配,可以通过无锁的mcache提升分配性能 。mcache不足时刻会拿mcentral的锁,然后从mcentral中充mspan 给mcache 。大对象直接从mheap 中分配 。
在x8664环境上,golang管理的有效的程序虚拟地址空间实质上只有48位 。在mheap中有一个pages pageAlloc成员用于管理golang堆内存的地址空间 。golang从os中申请地址空间给自己管理,地址空间申请下来以后,golang会将地址空间根据实际使用情况标记为free或者alloc 。如果地址空间被分配给mspan或大对象后,那么被标记为alloc,反之就是free 。
Golang认为地址空间有以下4种状态:
Golang同时定义了下面几个地址空间操作函数:
在mheap结构中,有一个名为pages成员 , 它用于golang 堆使用虚拟地址空间进行管理 。其类型为pageAlloc
pageAlloc 结构表示的golang 堆的所有地址空间 。其中最重要的成员有两个:
在golang的gc流程中会将未使用的对象标记为未使用,但是这些对象所使用的地址空间并未交还给os 。地址空间的申请和释放都是以golang的page为单位(实际以chunk为单位)进行的 。sweep的最终结果只是将某个地址空间标记可被分配,并未真正释放地址空间给os,真正释放是后文的scavenge过程 。
在gc mark结束以后会使用sweep()去尝试free一个span;在mheap.alloc 申请mspan时刻,也使用sweep去清扫一下 。
清扫mspan主要涉及到下面函数
如上节所述,sweep只是将page标记为可分配,但是并未把地址空间释放;真正的地址空间释放是scavenge过程 。
真正的scavenge是由pageAlloc.scavenge()—sysUnused()将扫描到待释放的chunk所表示的地址空间释放掉(使用sysUnused()将地址空间还给os)
golang的scavenge过程有两种:
Go语言有什么优势?GO语言的优势:可直接编译成机器码,不依赖其go语言动态生成大块内存他库,glibc的版本有一定要求,部署就是扔一个文件上去就完成go语言动态生成大块内存了 。静态类型语言,但是有动态语言的感觉,静态类型的语言就是可以在编译的时候检查出来隐藏的大多数问题,动态语言的感觉就是有很多的包可以使用,写起来的效率很高 。语言层面支持并发,这个就是Go最大的特色,天生的支持并发,我曾经说过一句话,天生的基因和整容是有区别的,大家一样美丽,但是你喜欢整容的还是天生基因的美丽呢?Go就是基因里面支持的并发,可以充分的利用多核,很容易的使用并发 。内置runtime,支持垃圾回收,这属于动态语言的特性之一吧,虽然目前来说GC不算完美,但是足以应付我们所能遇到的大多数情况,特别是Go1.1之后的GC 。简单易学,Go语言的作者都有C的基因,那么Go自然而然就有了C的基因 , 那么Go关键字是25个,但是表达能力很强大 , 几乎支持大多数你在其他语言见过的特性:继承、重载、对象等 。丰富的标准库,Go目前已经内置了大量的库,特别是网络库非常强大,我最爱的也是这部分 。内置强大的工具,Go语言里面内置了很多工具链,最好的应该是gofmt工具,自动化格式化代码,能够让团队review变得如此的简单,代码格式一模一样 , 想不一样都很困难 。跨平台编译,如果你写的Go代码不包含cgo,那么就可以做到window系统编译linux的应用 , 如何做到的呢?Go引用了plan9的代码,这就是不依赖系统的信息 。Go语言这么多的优势,你还不想学吗?我记得当时我看的是黑马程序员的视频,我对他们视频的印象就是通俗易懂 , 就是好!

推荐阅读