day8 高性能Go语言发行版优化与落地实践 |青训营笔记

148 阅读3分钟

题记

这是我参与「第五届青训营 」伴学笔记创作活动的第 8天,本文用于记录在青训营的学习笔记和一些心得。

day8 1月22日

本节课程:高性能Go语言发行版优化与落地实践

  • 优化

    • 内存管理优化
    • 编译器优化
  • 背景

    • 自动内存管理和Go内存管理机制
    • 编译器优化的基本问题和思路
  • 实践:字节跳动遇到的性能问题以及优化方案

追求极致性能

性能优化是什么?

  • 提升软件系统处理能力,减少不必要的消耗,充分发掘计算机算力。

为什么要做性能优化?

  • 用户体验:带来用户体验的提升——让刷抖音更丝滑,让双十—购物不再卡顿
  • 资源高效利用:降低成本,提高效率——很小的优化乘以海量机器会是显著的性能提升和成本节约

image-20230119135704988

image-20230119140448876

总结

  • 性能优化的基本问题
  • 性能优化的两个层面
  • 性能优化的可维护性

自动内存管理

  • 动态内存

    • 程序在运行时根据需求动态分配的内存: malloc ( )
  • 自动内存管理(垃圾回收):由程序语言的运行时系统回收动态内存

    • 避免手动内存管理,专注于实现业务逻辑
    • 保证内存使用的正确性和安全性: double-free problem, use-after-free problem
  • 三个任务

    • 为新对象分配空间
    • 找到存活对象
    • 回收死亡对象的内存空间

image-20230119142155087

image-20230119142908855

image-20230119144454442

image-20230119145336067

Copying GC:将对象复制到另外的内存空间

Mark-sweep GC:使用free list管理空闲内存

Compact GC:原地整理对象

image-20230119150936571

image-20230119151135036

Go内存管理以及优化

image-20230119185226541

image-20230119190934063

image-20230119192115648

image-20230119192516862

image-20230119193149357

image-20230119193157328

总结

  • Go内存管理-分块

  • Go内存管理—缓存

  • Go对象分配的性能问题

    • 分配路径过长
    • 小对象居多
  • Balanced GC

    • 指针碰撞风格的对象分配
    • 实现了copying Gc
    • 性能收益

编译器和静态分析

编译器的结构

  • 重要的系统软件

    • 识别符合语法和非法的程序
    • 生成正确且高效的代码
  • 分析部分(前端front end)

    • 词法分析,生成词素(lexeme)
    • 语法分析,生成语法树
    • 语义分析,收集类型信息,进行语义检查
    • 中间代码生成,生成intermediate representation (IR)
  • 综合部分(后端back end)

    • 代码优化,机器无关优化,生成优化后的lR
    • 代码生成,生成目标代码

image-20230119194000854

我们主要学习编译器后端优化

image-20230119195113020

image-20230119195623065

总结

  • 编译器的结构与编译的流程
  • 编译器后端优化
  • 数据流分析和控制流分析
  • 过程内分析和过程间分析

Go编译器优化

  • 为什么做编译器优化

    • 用户无感知,重新编译即可获得性能收益
    • 通用性优化
  • 现状

    • 采用的优化少
    • 编译时间较短,没有进行较复杂的代码分析和优化
  • 编译优化的思路

    • 场景:面向后端长期执行任务
    • Tradeoff:用编译时间换取更高效的机器码
  • Beast mode

    • 函数内联
    • 逃逸分析
    • 默认栈大小调整
    • 边界检查消除
    • 循环展开
    • ..............

image-20230119203124041

image-20230119203132505

image-20230119203150816

image-20230119204907651

image-20230119205807836

image-20230119205823119

课后

  1. 从业务层和语言运行时层进行优化分别有什么特点?
  2. 从软件工程的角度出发,为了保证语言 SDK 的可维护性和可拓展性,在进行运行时优化时需要注意什么?
  3. 自动内存管理技术从大类上分为哪两种,每一种技术的特点以及优缺点有哪些?
  4. 什么是分代假说?分代 GC 的初衷是为了解决什么样的问题?
  5. Go 是如何管理和组织内存的?
  6. 为什么采用 bump-pointer 的方式分配内存会很快?
  7. 为什么我们需要在编译器优化中进行静态代码分析?
  8. 函数内联是什么,这项优化的优缺点是什么?
  9. 什么是逃逸分析?逃逸分析是如何提升代码性能的?