惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LangChain Blog
S
SegmentFault 最新的问题
V
Visual Studio Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
美团技术团队
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
有赞技术团队
有赞技术团队
量子位
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
博客园 - 叶小钗
月光博客
月光博客
P
Proofpoint News Feed
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
博客园_首页
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
Stack Overflow Blog
Stack Overflow Blog

牛牛技术客栈

设计模式-备忘录模式 - OXOXTECH 牛牛技术客栈 设计模式-中介者模式 - OXOXTECH 牛牛技术客栈 Linux【Ubuntu】修改ssh默认端口 - OXOXTECH 牛牛技术客栈 设计模式-迭代器模式 - OXOXTECH 牛牛技术客栈 scheduled定时任务的三种基本实现方式 - OXOXTECH 牛牛技术客栈 Apriori - 基于关联规则的推荐算法(三) - OXOXTECH 牛牛技术客栈 Apriori - 基于关联规则的推荐算法(二) - OXOXTECH 牛牛技术客栈 Apriori - 基于关联规则的推荐算法(一) - OXOXTECH 牛牛技术客栈 基于JavaFX的桌面端网络调试工具 - OXOXTECH 牛牛技术客栈 Golang Channel的原理介绍 - OXOXTECH 牛牛技术客栈 Go语言Map的原理分析 - OXOXTECH 牛牛技术客栈 Go语言错误处理(panic)的最佳实践 - OXOXTECH 牛牛技术客栈 设计模式-解释器模式 - OXOXTECH 牛牛技术客栈 Redis报错Redis is configured to save RDB snapshots, but it's currently unable to persist to disk. go-webpbin库在Linux报错failed to encode image to WebP: exit status 1.......的问题 exe4j 打包加密的jar - OXOXTECH 牛牛技术客栈 Go生成图形验证码示例 - OXOXTECH 牛牛技术客栈 澳门一天游:一日尽享东方与西方的交融之美 - OXOXTECH 牛牛技术客栈 设计模式-命令模式 - OXOXTECH 牛牛技术客栈 别再自己瞎写工具类了,SpringBoot内置工具类应有尽有 - OXOXTECH 牛牛技术客栈 中山一日游 - OXOXTECH 牛牛技术客栈 设计模式-责任链模式 - OXOXTECH 牛牛技术客栈 起舞吧,齐舞吧 - OXOXTECH 牛牛技术客栈 设计模式-组合模式 - OXOXTECH 牛牛技术客栈 Go语言Web开发|GoFrame框架入门笔记 - OXOXTECH 牛牛技术客栈 Java打包exe教程 - OXOXTECH 牛牛技术客栈 设计模式-代理模式 - OXOXTECH 牛牛技术客栈 MySQL存储过程的优缺点有哪些? - OXOXTECH 牛牛技术客栈 前端渲染优化有哪些? - OXOXTECH 牛牛技术客栈 HTTP状态码及其含义 - OXOXTECH 牛牛技术客栈
Golang逃逸分析 - OXOXTECH 牛牛技术客栈
军阁 · 2024-04-23 · via 牛牛技术客栈

军阁 Go Golang

什么是逃逸

内存从栈逃逸到堆中,会增大GC的压力

为什么要做逃逸分析

申请到栈内存性能好,不会引起GC,函数返回直接释放

申请到堆内存会导致gc,引起性能问题

如何分配:

  1. 如果函数外部没有引用,则优先放到栈中;
  2. 如果函数外部存在引用,则必定放到堆中;

常见的三种逃逸

指针逃逸

函数返回局部变量的指针导致指针逃逸

package main
func pointerEscapeFunc() *int{
    var v int
    return &v
}

func main(){
    pointerEscapeFunc()//v会被分配到堆上
    return
}

输出:

host$ go build -gcflags '-m -l' tem.go #-m打印信息,-l忽略inline信息
# command-line-arguments
./tem.go:3:6: moved to heap: v #可见v被分配到了堆上

栈空间不足

go的goroutine初始栈大小为2KB,go可以增大栈大小,但不可超过系统栈限制(使用ulimit -s查看),超过一定大小的变量将会逃逸到堆上,不同go版本大小限制不同

package main
func stackSpaceExhausted(){
    v := make([]int,0,10000)
}

func main(){
    stackSpaceExhausted()
}

输出:

host$ go build -gcflags '-m -l' tem.go 
# command-line-arguments
./tem.go:3:11: make([]int, 0, 10000) escapes to heap # 可见逃逸到了堆上,go1.15

闭包引用

函数类型也分两种,一种是函数字面量类型(未命名类型,func literal),另一种是函数命名类型。

package main
func outer() func() int{
    var a int
    return func() int{
        a++
        return a
    }   
}

func main(){
    inner := outer()
    print(inner())
}

输出:

host$ go build -gcflags '-m -l' tem.go 
# command-line-arguments
./tem.go:3:6: moved to heap: a
./tem.go:4:9: func literal escapes to heap

动态类型

对象大小不确定或作为不确定大小的参数时发生逃逸

package main
import "fmt"
func main(){
    var a int
    fmt.Println(a)//fmt.Println的入参是...interface{}
}

输出:

host$ go build -gcflags '-m -l' tem.go 
# command-line-arguments
./tem.go:7:13: main ... argument does not escape
./tem.go:7:13: a escapes to heap

逃逸分析使用

传值会拷贝对象,增加对象拷贝开销(听君一席话,胜似一席话),只读切内存小的结构体使用可以提高性能

传指针会导致内存逃逸到堆中,增加垃圾回收(GC)负担,对象需要频繁创建删除时,GC开销会特别大,影响性能,但在需要修改对象值、内存占用大的结构体中,传指针性能更好

转载自: https://longtao.fun/metaverse/escapeanalysis/