• Golang运行时垃圾收集原理及调优


    Golang垃圾收集原理

            Go编译生成的目标程序会嵌入一个go运行时,里面包括一个垃圾收集器,类似java的虚拟机中的垃圾收集器,它负责收集并清理不再使用的内存空间。

    不在垃圾收集范围内

            Go的标量基本数据类型不在垃圾收集的范围内,因为它们存在于goroutine stack 中,随着方法的结束而释放,这些变量类型有 uint、byte、指针等,垃圾收集主要管理堆区的内存。

    垃圾收集采用的方式

            Go垃圾收集采用 标记-清理 方式来管理内存,当触发垃圾收集阈值时,首先标记不再适用的内存,然后清理掉用它们。

    标记内存的方式

            采用对象图方式,标记初始阶段,go 会枚举根节点roots,能够作为根节点的有 本地变量、全局变量,从roots开始分析所有不可到达的内存引用。

    GC的成本

            1.GC运行时程序代码会暂停

            2.GC会消耗CPU和内存

    GO垃圾收集(简称GOGC)方式

            GOGC根据当前活动堆大小使用配置的GOGC值(允许的当前Live Heap峰值内存百分比)来决定是否启动垃圾收集,比如当前活动堆大小20MB,GOGC 设置为 100 ,当新分配内存堆峰值内存大于20MB时将触发垃圾收集。

    如图

    可以知道当GOGC设置的越小垃圾收集就会越频繁。

    Go MemoryLimit(在Go 1.19版本可用)

            设置Go运行时可使用的堆内存,该限制并不是强制性,如设置Limit=20MB,程序实际需要100MB,实际也能够分配到100MB,但是垃圾收集器会频繁进行GC来试图保持不可能到达的Limit值。

    GOGC配置推荐规则

     1.当部署程序到完全可控的环境下,建议根据实际需要设置MemoryLimit。

     2.GO程序与其它程序一起运行时不要关闭GOGC,关闭GOGC会导致耗尽内存影响到其它进程。

     3.部署到不可控的环境下时不要设置MemoryLimit(如 云环境 容器等)

    GOGC实践(由于GO 1.19还未发布,无法测试MemoryLimit特性)

    1. func main() {
    2. //设置GOGC峰值分配内存百分比
    3. debug.SetGCPercent(100)
    4. data := make([][]byte, 0)
    5. for index := 0; index < 10; index++ {
    6. //分配100MB
    7. var buff []byte = make([]byte, 1024*1024*100)
    8. for i := range buff {
    9. buff[i] = 111
    10. }
    11. //data = append(data, buff)
    12. time.Sleep(time.Duration(2 * time.Second))
    13. fmt.Println(len(buff))
    14. fmt.Println(len(data))
    15. }
    16. }

     设置GOGC=100,在整个运行期间将保持合适的内存,程序总共分配了1G内存,活动堆内存为100MB,由于GOGC设置了100%,所以分配的峰值内存为100MB,所以程序始终保持200MB左右的内存。

     

    保持分配内存存活(关联gc roots节点),GOGC=100,每次分配200MB,其中100MB关联到roots链,另外100MB不关联,当程序运行时始终保持合适的内存值。

     

    关闭GOGC时,内存占用会保持实际分配的内存量

  • 相关阅读:
    FLASK 模板,渲染变量
    MD5 到底算不算一种加密算法?
    宝玉:Sora 如何改变我们的生活
    药物研发检测记录模板-0903不溶性微粒检查法检验原始记录
    用工具实现 Mock API 的整个流程
    面试素材-结构化
    Vue 调用方法要不要加括号?
    html web前端,登录,post请求提交 json带参
    到底怎么个DAO
    springboot15:junit5的使用
  • 原文地址:https://blog.csdn.net/vs2008ASPNET/article/details/126160097