文章

golang - 内存篇

golang - 内存篇

go的GC

Garbage Collection (GC)是⼀种⾃动管理内存的⽅式。⽀持GC的语⾔⽆需⼿动管理内存,程序后台⾃动判断对象。是否存活并回收其内存空间,使开发⼈员从内存管理上解脱出来。

1
2
如果不释放会造成内存泄露!开发语言提供了垃圾回收 就不需要⼿动释放内存空间。
垃圾回收机制:引⽤计数、标记清除、三⾊标记、分代收集。

三⾊标记, 并发标记和清扫,⾮分代,⾮紧缩,混合写屏障。

1
2
3
4
5
6
7
三⾊标记
step1:有⿊⽩灰三个集合,初始时所有对象都是⽩⾊
step2:从Root对象开始标记, 将所有可达对象标记为灰⾊
step3:从灰⾊对象集合取出对象, 将其引⽤的对象标记为灰⾊, 放⼊灰⾊集合, 并将⾃⼰标记为⿊⾊
step4:重复第三步(step3), 直到灰⾊集合为空, 即所有可达对象都被标记
step5:标记结束后, 不可达的⽩⾊对象即为垃圾. 对内存进⾏迭代清扫,回收⽩⾊对象
重置GC状态

参考代码地址:

1
2
3
4
5
/src/runtime/mgc.go

/src/runtime/malloc.go

/src/runtime/gc_test.go

/src/runtime/mgc.go

/src/runtime/malloc.go

Go语言的GC(垃圾收集)在运行时是并发的,这意味着它会在程序运行时的某个时间点开始工作,而不会阻塞整个程序。这是通过Go运行时的协程(goroutine)实现的,而不是使用操作系统层面的线程(thread)。

当GC需要在堆上移动对象来 rebalance 空间时,它会在后台进行,不会中断正常的应用程序执行。这是Go语言内存管理的一个核心优势,因为它减少了程序的暂停时间,提高了整体的响应性。

简而言之,Go在GC时使用协程来进行并发操作,而不是使用操作系统层面的线程。这是Go语言内存管理的一个核心特性,它使得Go程序具有低延迟和高并发的特点。

垃圾清理阶段:

  1. 清理准备阶段-暂停 STW (Stop The World)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    在GC发生过程中,会产生应用程序的停顿,整个应用程序都会暂停。
    应用程序的其他所有Go routine都会暂停,直到垃圾收集过程完成。
    确保分析整个期间,数据状态的一致性。
     Go1.5版本之前,垃圾收集器是和应用程序代码并发执行的,这被称为并发标记清除(Concurrent Mark and Sweep, CMS)。
        
     Go 1.5版本开始-1.14之前,垃圾收集器默认采用了并发标记清除和并发预清理(Concurrent Preclean)技术,这使得垃圾收集过程更加平滑,减少了全 stop-the-world 的时间。
        
    在Go 1.14版本之前,垃圾收集器采用的是三色标记(Tri-color Marking)算法,1.14版本开始,垃圾收集器引入了更加高效的垃圾收集算法,如Shopcliff算法,这使得垃圾收集器能够进一步提高回收效率和减少停顿时间。
    优化目的:为了减少GC对应用程序的影响,尽可能地减少全局的停顿时间。
    
1
2
3
4
5
1. 清理准备阶段-暂停 STW (Stop The World)  ->  
  在GC发生过程中,会产生应用程序的停顿,整个应用程序都会暂停。
标记阶段  -> 
标记终止阶段  -> 

https://blog.csdn.net/qq_56999918/article/details/127538969

https://blog.csdn.net/2401_84904997/article/details/138689587

https://blog.csdn.net/weixin_45901764/article/details/120972956

golang - 内存溢出、泄露、逃逸

主要是为了避免开发期间踩的坑。

内存溢出

内存溢出(Out Of Memory,简称OOM)‌是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。

对比【内存泄漏】(指程序在申请内存后,无法释放已申请的内存空间,导致内存的浪费。)内存溢出则是指程序在运行过程中,向操作系统申请的内存空间已经用完,再次申请内存空间时无法获得需要的内存空间而导致程序崩溃的现象‌。

内存泄漏

内存泄露是指程序在运行过程中持有不再需要的内存,导致GC无法回收这部分内存,从而随着程序运行时间的增加消耗更多系统资源。

内存逃逸

内存逃逸是指原本应该在栈上分配的内存被分配到了堆上。

本文由作者按照 CC BY 4.0 进行授权