问题

简单讲讲golang的内存逃逸吗?

解析

什么是内存逃逸

在程序中,每个函数块都会有自己的内存区域用来存自己的局部变量(内存占用少)、返回地址、返回值之类的数据,这一块内存区域有特定的结构和寻址方式,寻址起来十分迅速,开销很少。这一块内存地址称为栈。栈是线程级别的,大小在创建的时候已经确定,当变量太大的时候,会"逃逸"到堆上,这种现象称为内存逃逸。简单来说,局部变量通过堆分配和回收,就叫内存逃逸。

内存逃逸的危害

堆是一块没有特定结构,也没有固定大小的内存区域,可以根据需要进行调整。全局变量,内存占用较大的局部变量,函数调用结束后不能立刻回收的局部变量都会存在堆里面。变量在堆上的分配和回收都比在栈上开销大的多。对于 go 这种带 GC 的语言来说,会增加 gc 压力,同时也容易造成内存碎片。

如何分析程序是否发生内存逃逸

build时添加-gcflags=-m 选项可分析内存逃逸情况,比如输出./main.go:3:6: moved to heap: x 表示局部变量x逃逸到了堆上。

内存逃逸发生时机

  1. channel 发送指针数据。因为在编译时,不知道channel中的数据会被哪个 goroutine 接收,因此编译器没法知道变量什么时候才会被释放,因此只能放入堆中。
package main
func main() {
ch := make(chan int, 1)
x := 5
ch <- x // x不发生逃逸,因为只是复制的值
ch1 := make(chan *int, 1)
y := 5
py := &y
ch1 <- py // y逃逸,因为y地址传入了chan中,编译时无法确定什么时候会被接收,所以也无法在函数返回后回收y
}
  1. 局部变量在函数调用结束后还被其他地方使用,比如函数返回局部变量指针或闭包中引用包外的值。因为变量的生命周期可能会超过函数周期,因此只能放入堆中。
package main

func Foo () func (){
x := 5 // x发生逃逸,因为在Foo调用完成后,被闭包函数用到,还不能回收,只能放到堆上存放
return func () {
x += 1
}
}
func main() {
inner := Foo()
inner()
}
  1. 在 slice 或 map 中存储指针。比如 []*string,其后面的数组可能是在栈上分配的,但其引用的值还是在堆上。
package main
func main() {
var x int
x = 10
var ls []*int
ls = append(ls, &x) // x发生逃逸,ls存储的是指针,所以ls底层的数组虽然在栈存储,但x本身却是逃逸到堆上
}
  1. 切片扩容后长度太大,导致栈空间不足,逃逸到堆上。
package main

func main() {
s := make([]int, 10000, 10000)
for index, _ := range s {
s[index] = index
}
}
  1. 在 interface 类型上调用方法。 在 interface 类型上调用方法时会把interface变量使用堆分配, 因为方法的真正实现只能在运行时知道。
package main
type foo interface {
fooFunc()
}
type foo1 struct{}
func (f1 foo1) fooFunc() {}
func main() {
var f foo
f = foo1{}
f.fooFunc() // 调用方法时,f发生逃逸,因为方法是动态分配的
}

避免内存逃逸的办法

  • 对于小型的数据,使用传值而不是传指针,避免内存逃逸。
  • 避免使用长度不固定的slice切片,在编译期无法确定切片长度,只能将切片使用堆分配。
  • interface调用方法会发生内存逃逸,在热点代码片段,谨慎使用。

写在最后

喜欢本文的朋友,欢迎关注公众号「会玩 code」,专注大白话分享实用技术。

简单聊聊内存逃逸 | 剑指offer - golang的更多相关文章

  1. 《剑指offer(第二版)》面试题64——求1+2+...+n

    一.题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字以及条件判断语句 (即三元运算符,A? B : C) 二.题解 虽然求和问 ...

  2. 【剑指Offer】简单部分每日五题 - Day 1

    今天开始更新leetcode上<剑指Offer>的题解,先从简单难度开始.预计按下列顺序更新: 简单难度:每日5题 中等难度:每日3题 困难难度:每日1题 17 - 打印从1到最大的n位数 ...

  3. [简单-剑指 Offer 53 - II. 0~n-1中缺失的数字]

    [简单-剑指 Offer 53 - II. 0-n-1中缺失的数字] 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0-n-1之内.在范围0-n-1内的n个数字中有且只有一 ...

  4. [简单-剑指 Offer 53 - I. 在排序数组中查找数字 I]

    [简单-剑指 Offer 53 - I. 在排序数组中查找数字 I] 统计一个数字在排序数组中出现的次数. 示例 1: 输入: nums = [5,7,7,8,8,10], target = 8 输出 ...

  5. 剑指 Offer 61. 扑克牌中的顺子 + 简单题 + 思维

    剑指 Offer 61. 扑克牌中的顺子 Offer_61 题目描述 java代码 package com.walegarrett.offer; /** * @Author WaleGarrett * ...

  6. 剑指 Offer 58 - II. 左旋转字符串 + 简单题

    剑指 Offer 58 - II. 左旋转字符串 Offer_58_2 题目描述 java代码 package com.walegarrett.offer; /** * @Author WaleGar ...

  7. 剑指offer计划16( 排序简单)---java

    1.1.题目1 剑指 Offer 45. 把数组排成最小的数 1.2.解法 这题看的题解,发现自己思路错了. 这里直接拿大佬的题解来讲吧. 一开始这里就把创一个string的数组来存int数组 Str ...

  8. 面试题目——《剑指Offer》

    1.把一个字符串转换成整数——<剑指Offer>P29 2.求链表中的倒数第k个结点——<剑指Offer>P30 3.实现Singleton模式——<剑指Offer> ...

  9. [读]剑指offer

    研二的开始找工作了,首先祝愿他们都能够找到自己满意的工作.看着他们的身影,自问明年自己这个时候是否可以从容面对呢?心虚不已,赶紧从老严那儿讨来一本<剑指offer>.在此顺便将自己做题所想 ...

随机推荐

  1. Android 开发学习进程0.30 builder模式创建popwindow

    builder模式创建自定义popwindow builder设计模式 将一个复杂的对象构建与它的表示分离,简化代码的使用方式.当对象有多个参数或多个零件同时初始化方法同时初始化方法有默认值时,采用此 ...

  2. Android学习之 AlertDialog

    •AlertDialog简介 AlertDialog 可以在当前界面弹出一个对话框: 这个对话框是置顶于所有界面元素之上的,能够屏蔽掉其他控件的交互能力: 因此, AlertDialog 一般用于提示 ...

  3. java进阶(38)--线程安全

    文档目录: 一.概念 二.解决方案 三.举例说明 ---------------------------------------分割线:正文------------------------------ ...

  4. 亲自动手实现Python+pygame中国象棋游戏

    功能1:实现游戏整体界面显示 一.创建基本的结构 代码如下: import time import pygame def main(): # 初始化pygame pygame.init() # 创建用 ...

  5. && 与 || 差在哪?-- Shell十三问<第十问>

    && 与 || 差在哪?-- Shell十三问<第十问> 好不容易,进入两位数的章节了... 一路走来,很辛苦吧?也很快乐吧? 在解答本章题目之前,先让我们了解一个概念:r ...

  6. 原生php 实现 thinkphp 数据库链式操作!!!

    https://www.bilibili.com/video/BV1v4411A74Q?p=16&spm_id_from=pageDriver 没事可以看两遍,加深一下基础知识!!!

  7. 机器学习--如何理解Accuracy, Precision, Recall, F1 score

    当我们在谈论一个模型好坏的时候,我们常常会听到准确率(Accuracy)这个词,我们也会听到"如何才能使模型的Accurcy更高".那么是不是准确率最高的模型就一定是最好的模型? 这篇博文会向大家解释 ...

  8. 关于C语言解决汉诺塔(hanoi)问题

    C语言解决汉诺塔问题 汉诺塔是典型的递归调用问题: hanoi简介:印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑夜,总有一个僧侣 ...

  9. 并发编程(ReentrantLock&&同步模式之顺序控制)

    4.13 ReentrantLock 相对于 synchronized 它具备如下特点 可中断 可以设置超时时间 可以设置为公平锁 支持多个条件变量,即对与不满足条件的线程可以放到不同的集合中等待 与 ...

  10. 【笔记】《算法竞赛入门》习题7-6 UVa12113_重叠的正方形

    title: 习题7-6 UVa12113_重叠的正方形 date: 2021-01-31 19:08:00 categories: 算法竞赛入门 tags: 数据结构 算法 UVa <算法竞赛 ...