【Go语言的垃圾回收机制(2)】

简介: 【Go语言的垃圾回收机制(2)】

精确的垃圾回收


像C语言这种不支持垃圾回收的语言,其实还是有些垃圾回收的库可以使用的。这类库一般也是用的标记清扫算法实现的,但是它们都是保守的垃圾回收。之所以叫“保守”是因为它们没办法获取对象类型信息,因此只能保守地假设地址区间中每个字都是指针。


无法获取对象的类型信息会造成什么问题呢?这里举个例子来说明。


假设某个结构体中是不包含指针成员的,那么对该结构体成员进行垃圾回收时,其实是不必要递归地标记结构体的成员的。但是由于没有类型信息,我们并不知道这个结构体成员不包含指针,因此我们只能对结构体的每个字节递归地标记下去,这显然会浪费很多时间。这个例子说明精确的垃圾回收可以减少不必要的扫描,提高标记过程的速度。


这个例子说明,保守的垃圾回收某些情况下会出现垃圾无法被回收的情况。虽然不会造成大的问题,但总是让人很不爽,都是没有类型信息惹的祸。


现在好了,在Go语言的 1.1 版本中开始支持精确的垃圾回收。精确的垃圾回收首先需要的就是类型信息,上一节中讲过 MSpan 结构体,类型信息是存储在 MSpan 中的。从一个地址计算它所属的 MSpan,公式如下:


页号 = (地址 - mheap.arena_start) >> 页大小

MSpan = mheap->map[页号]


1.接下来通过 MSpan->type 可以得到分配块的类型。这是一个 MType 的结构体:

struct  MTypes
{
    byte         compression;         //  one  of  MTypes_*
    bool         sysalloc;            //  whether  (void*)data  is  from  runtime·SysAlloc uintptr         data;
};

2.MTypes

MTypes 描述 MSpan 里分配的块的类型,其中 compression 域描述数据的布局。它的取值为 MTypes_Empty、MTypes_Single、MTypes_Words、MTypes_Bytes 四个中的一种:

MTypes_Empty:所有的块都是 free 的,或者这个分配块的类型信息不可用。这种情况下 data 域是无意义的。

MTypes_Single:这个 MSpan 只包含一个块,data 域存放类型信息,sysalloc 域无意义。

MTypes_Words:这个 MSpan 包含多个块(块的种类多于 7)。这时 data 指向一个数组 [NumBlocks]uintptr,数组里每个元索存放相应块的类型信息。

MTypes_Bytes:这个 MSpan 中包含最多 7 种不同类型的块。这时 data 域指下面这个结构体


struct  {
    type    [8]uintptr               //  type[0]  is  always  0
    index   [NumBlocks]byte
}


第 i 个块的类型是 data.type[data.index[i]]


表面上看 MTypes_Bytes 好像最复杂,其实这里的复杂程度是 MTypes_Empty 小于 MTypes_Single 小于 MTypes_Bytes 小于 MTypes_Words 的。MTypes_Bytes 只不过为了做优化而显得很复杂。


上一节中说过,每一块 MSpan 中存放的块的大小都是一样的,不过它们的类型不一定相同。如果没有使用,那么这个 MSpan 的类型就是 MTypes_Empty。如果存一个很大块,大于这个 MSpan 大小的一半,因此存不了其它东西了,那么这个 MSpan 的类型是 MTypes_Single。


假设存了多种块,每一块用一个指针,本来可以直接用 MTypes_Words 存的。但是当类型不多时,可以把这些类型的指针集中起来放在数组中,然后存储数组索引。这是一个小的优化,可以节省内存空间。


得到的类型信息最终其实是一个这样的结构体:


struct  Type
{
    uintptr  size;
    uint32  hash;
    uint8  _unused;
    uint8  align;
    uint8  fieldAlign;
    uint8  kind;
    Alg  *alg;
    void  *gc;
    String  *string;
    UncommonType  *x;
    Type  *ptrto;
};

不同类型的类型信息结构体略有不同,这个是通用的部分。可以看到这个结构体中有一个 gc 域,精确的垃圾回收就是利用类型信息中这个 gc 域实现的。


写在最后


最后:

🐱对于刚刚入门的同学,❀多少听起来会有点迷糊,话🌷但是没关系,不妨去牛客看一看对于go新生肯定会有很大的帮助滴。不要着急,不要慌,月亮下面有月光,循着月光找月亮,🌜🌜🌜快来🐂牛客🐂吧!

目录
相关文章
|
3天前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
23 13
|
3天前
|
网络协议 安全 Go
Go语言的网络编程基础
【10月更文挑战第28天】Go语言的网络编程基础
17 8
|
2天前
|
Go
go语言的复数常量
【10月更文挑战第21天】
13 6
|
2天前
|
Go
go语言的浮点型常量
【10月更文挑战第21天】
9 4
|
2天前
|
编译器 Go
go语言的整型常量
【10月更文挑战第21天】
7 3
|
2天前
|
Serverless Go
Go语言中的并发编程:从入门到精通
本文将深入探讨Go语言中并发编程的核心概念和实践,包括goroutine、channel以及sync包等。通过实例演示如何利用这些工具实现高效的并发处理,同时避免常见的陷阱和错误。
|
2天前
|
安全 Go 开发者
代码之美:Go语言并发编程的优雅实现与案例分析
【10月更文挑战第28天】Go语言自2009年发布以来,凭借简洁的语法、高效的性能和原生的并发支持,赢得了众多开发者的青睐。本文通过两个案例,分别展示了如何使用goroutine和channel实现并发下载网页和构建并发Web服务器,深入探讨了Go语言并发编程的优雅实现。
9 2
|
21天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
44 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
2月前
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。
|
29天前
|
存储 Java PHP
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
46 0