Java架构师-十项全能:打造高度深度广度兼备的全面技术人才

鲍忠
• 阅读 343

Java架构师-十项全能:打造高度深度广度兼备的全面技术人才

Golang记忆调谐 逃逸分析(逃逸分析) 在程序编译阶段,根据程序代码中的数据流,静态分析代码中哪些变量需要分配在堆栈空间上,哪些变量需要分配在堆栈空间上。一个理想的逸出分析算法,能够将开发者认为需要分配的变量尽可能多地保留在堆栈空间上,尽可能少地“逸出”到堆栈空间。理想太丰满,现实却很骨感。不同的语言情况,不同的语言版本,转义算法的准确性和实际优化是不一样的。对于开发者来说,只需要掌握逃逸分析工具和逃逸分析目标即可。 Golang语言的转义分析算法有两个版本。go1.13.6 darwin/amd64之后的版本由马修·登普斯基(Matthew Dempsky)大哥改写。它在源代码的src/cmd/compile/internal/GC/escape . go文件中,有详细的注释。有兴趣可以看看。虽然只有1000多行代码,而且有完整的算法描述和代码注释,但还是很“硬头”。 源文件注释了Golang语言转义分析算法的原理,是内存转义的指导思想。有两个基本不变量:

我们必须确保的两个关键不变量是: (1)指向堆栈对象的指针不能存储在堆中 (2)指向堆栈对象的指针不能比该对象更长寿(例如,因为声明函数返回并破坏了对象的堆栈帧,或者其空间在逻辑上不同的变量的循环迭代中被重用)。

指向堆栈对象的指针不能存储在堆中。 指向stack对象的指针不能超过stack对象的生存期(也就是说,在stack对象被销毁后,指针不能存活)。

逃逸分析算法的一般原理和过程在注释中也有说明。一般步骤是:

Golang编译器解析Golang源文件并获得抽象语法树(AST)。 构造一个有向加权图,遍历有向加权图,寻找可能违反上述两个不变量的赋值路径。如果变量的地址存储在堆中或其他可能超过其生存期的地方,该变量将被标记为需要在堆上分配。 在分析函数间的数据时,转义分析算法记录了每个函数的数据流,具体算法可以移到源代码中。

虽然不能通过new、make或literal的方式显式指定变量的分配位置,但是通过转义分析可以知道变量是分配到堆栈空间还是堆空间,这样可以提高热接口的响应,优化内存,提高GC效率,避免OOM。日常开发中,不需要详细了解逃逸分析算法的工作原理。只有使用Golang的工具链,才能使用逃逸分析算法进行逃逸分析。 诊断器具 使用编译工具 通过编译工具查看详细的转义分析过程,命令:gobuild-gcflags'-m-l 'xxxx.go。 编译参数(-gcflags):

-N:禁止编译优化。 -l:禁止内联。 -m:逃逸分析 -benchmem:在压力测量期间打印内存分配统计数据。

比如局部变量badBoy是在main函数中声明的,但是局部变量不是从外部捕获的,理论上会在函数栈上分配。 主包装

类型人员结构{ 名称字符串 EnName字符串 }

func main() { 坏男孩:= &Person{ 姓名:“法外狂徒张三”, EnName:“张三”, } _ =坏男孩 } 复制代码 输入命令:go build -gcflags '-m -l' main.go,传入-l关闭inline,从而屏蔽inline对最终生成代码的影响。

逃逸分析总结

堆栈空间分配内存比堆空间分配内存更高效,不同版本的Golang优化不同。本文基于go1.13.6 darwin/amd64。 逸出分析的目的是确定内存分配地址是堆栈空间还是堆空间。对于开发人员来说,无法通过new、make或literal来指定分配空间。 转义分析是在编译阶段完成的,可以通过编译工具分析,也可以反编译生成汇编代码,前者方便快捷,后者准确。 对于大型局部变量和大型内存,使用容器类型:切片、映射、数组。为了获得最佳性能,最好指明长度并将其分配给堆栈。对于肯定会转义到堆的变量,要知道是否会被捕获,循环引用会导致GC失败。 Golang系统提供的函数,底层方法在运行时反射类型、生成对象时,会有内存转义,所以在业务代码中尽量少用反射,一方面提高了代码的可读性,另一方面也给底层方法留下了“转义”的机会。 在日常开发中,无论是分配到栈空间还是堆空间,都不需要太在意。你只需要知道常见的逃逸场景,遇到OOM的时候有思路去查,去优化。 download:Java架构师-十项全能:打造高度深度广度兼备的全面技术人才

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
2年前
Java运行状态分析2:获取线程状态及堆栈信息
Java运行状态分析2:线程状态及堆栈信息基本概念出现内存泄漏或者运行缓慢场景,有时候无法直接从业务日志看出问题时候,需要分析jvm内存和线程堆栈线程堆栈信息主要记录jvm线程在某时刻线程执行情况,分析线程状态可以跟踪到程序出问题的地方​内存堆栈信息主要记录jvm堆中在某时刻对象使用情况,
Wesley13 Wesley13
2年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
2年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Stella981 Stella981
2年前
Linux应急响应(四):盖茨木马
0x00前言Linux盖茨木马是一类有着丰富历史,隐藏手法巧妙,网络攻击行为显著的DDoS木马,主要恶意特点是具备了后门程序,DDoS攻击的能力,并且会替换常用的系统文件进行伪装。木马得名于其在变量函数的命名中,大量使用Gates这个单词。分析和清除盖茨木马的过程,可以发现有很多值得去学习和借鉴的地方。0x01应急场景
Easter79 Easter79
2年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Wesley13 Wesley13
2年前
C语言内存优化——继续含泪总结
之前分析了基本数据类型的优化,现在开始涉及全局和局部变量的优化,话说这个东西我从没想过还能这样优化的喂!全局变量/Globalvariables全局变量不会被分配在寄存器上,修改全局变量需要通过指针或者调用函数的方式间接进行。所以编译器不会将全局变量存储在寄存器中,那样会带来额外的、不必要的负担和存储空间。所以在比较关键的循环中,我们要
贾蓁 贾蓁
3个月前
体系课-2022Java架构师十项全能40周「完结无密」|对标阿里P8
体系课2022Java架构师十项全能40周「完结无密」|对标阿里P8Java架构师十项全能download》http://quangneng.com/2724/成为一名全能的Java架构师需要具备广泛的技能和深厚的经验。以下是Java架构师可能需要的十项全
乐和 乐和
1个月前
Java架构师十项全能|完结无密
Java架构师十项全能|完结无密download》chaoxingit.com/1812/Java架构师十项全能:打造卓越的Java开发团队随着Java技术的广泛应用,Java架构师的角色越来越重要。一个优秀的Java架构师需要具备多项全能技能,包括Jav
韦康 韦康
3星期前
体系课-2022Java架构师十项全能40周「完结无密」|对标阿里P8
体系课2022Java架构师十项全能40周「完结无密」|对标阿里P8download:quangneng.com/2724/2022年,Java架构师十项全能:40周系统进阶之路在当今的软件开发领域,Java架构师是一个备受尊敬的角色。他们不仅需要具备深厚