【青训营】Go语言性能优化 | 青训营笔记

111 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记。本文介绍Go语言内存管理的问题及优化方法。

前言

性能优化是指提升软件系统处理的能力,减少不必要的消耗,充分发掘计算机算力。做性能优化的优点:不仅可以提高用户体验还能高效利用资源,降低成本。

业务代码层优化:针对特定场景,具体问题具体分析。语言运行时优化:解决更通用性的问题,考虑更多场景,可以使用Tradeoffs。

一、自动内存管理

1.自动内存管理-相关概念

动态内存:程序在运行时根据需求动态分配的内存

自动内存管理(垃圾回收):由程序语言运行时系统回收动态内存。其优点是程序员可以避免手动内存管理,专注于实现业务逻辑;保证内存使用的安全性和正确性。

Mutator:业务线程,分配新对象,修改对象指向关系

Collector:GC线程,找到存活对象,回收死亡对象的内存空间

Serial GC:只有一个collector

Parallel GC:支持多个collectors同时回收的GC算法

Concurrent GC:mutator和collector可以同时执行

2.追踪垃圾回收

  • 对象被回收的条件是指针指向关系不可达的对象

  • 标记根对象

    • 静态变量、全局变量、常量、线程等
  • 标记找到可达对象

    • 求指针指向关系的传递闭包:从根对象出发,找到所有可达对象
  • 清理所有不可达对象

    • 将存活的对象复制到另外的内存空间(Copying GC)
    • 将死亡对象的内存标记为可分配(Mark-sweep GC,使用free list管理空闲内存
    • 移动并整理存活对象(Mark-compact GC),原地整理对象

二、Go内存管理及优化

优化方案 Balanced GC

  • 每个g都绑定一个大块内存(1KB),称作goroutine allocation buffer(GAB)
  • GAB用于noscan类型的小对象分配:< 128B
  • 使用三个指针维护GAB:base,end,top
  • Bump pointer(指针碰撞)风格对象匹配
    • 无须和其他请求互斥
    • 分配动作简单高效 GAB对于Go内存来说是一个对象

本质:将多个小对象的内存合并成一次对象的分配

问题:GAB的对象分配方式会导致内存被延迟释放

优化方案:移动GAB中存活的对象

  • 当GAB总大小超过一定阈值时,将GAB中存活的对象复制到另外分配的GAB中
  • 原先的GAB可以释放,避免内存泄露
  • 本质:用copying GC 的算法管理小对象