5.内存分配和垃圾回收

  1. 1.gc时扫描栈区是不是只有 检查有没有栈区的对象指向堆区对象 这一个作用?栈区在函数调用结束时会自动回收函数占用的空间,是否代表函数占据的空间理论上不需要gc这种算法去做垃圾回收?
  2. 2.GMP有的人说1/61并不是每隔60次去全局队列中找,而是每次都1/61的概率去全局队列中找,哪个对呢?
  3. 3.Go1.8之后的混合写屏障,怎么具体防止了 黑色新指向白色且被灰色不可达 导致的数据丢失?混合写屏障只优化了重新扫描栈,但没有优化延迟清理?
  4. 4.如果说逃逸分析是编译时的,但是我在占上分配一个运行时才能确定长度的slice,那逃逸分析是会被无效么?
  5. 5.怎样理解 Happens Before?
  6. 6.m0主要做了什么事情。m0和其他m区别么
  7. 7.channel的实现原理,直接拷贝 发生在什么时候?
  8. 8.defer的实现原理,以及开放编码是怎么回事?
  9. 9.链表对GC不友好,这句话对吗?
  10. 10.进入gc.markDone()时是已经标记完成了吗,然后再进入gcMarkTermination进行sweep吗? 还有Yuasa感觉会产生浮动垃圾,g1收集器好像也是Yuasa,它好像快照完,所有快照的引用不管是不是垃圾都不回收,然后下次再回收,导致有浮动垃圾
  11. 11.为什么栈上开写屏障开销高?
  12. 12.go 的map什么时候等量扩容?PPt看了又不理解了。
  13. 13.error类型是小写,为啥可在其他包中引用?看到书里说是预定义标识符,是全局块的一部分
  14. 14.曹大,channel调试的流程能简单演示一下吗
  15. 15.fatal error 错误 写测试的 时候是不是没有办法抓到处理?
  16. 16.gc的触发时机,runtime.mallocgc,不太理解
  17. 17.GMP, g和m分别有具体的结构体,那p具体在源码上是什么呢?
  18. 18.程序刚启动,main.main作为主goroutine怎么绑定P,g0怎么工作,以及在main函数里go func,怎么新启动M和偷窃、调度?
  19. 19.os.Exit不会执行defer,是不会执行子goroutine的defer、只会调用main函数的的defer对吗?那子goroutine里面调用函数的defer怎么才能正常执行到呢?kill哪个命令对应的是os.Exit?
  20. 20.cgo 代码如何调试?怎么捕获内存分配信息
  21. 21.现在想准备跳槽,系统方面有什么书可以推荐,go的课程信心挺足,系统方面都没头绪,不知道怎么准备,目标公司B站
  22. 23.蚂蚁线上一个服务是几个pod做负载均衡?
  23. 23.现在工作一两年的面试已经八股文全覆盖了,工作年限再高一些问啥?
  24. 24.面试有问为什么要内存对齐,和高速缓存有什么关系。
  25. 25.a:=make([]*Person,0,0) 和 a:=[]*Person{} 这两种分配有区别吗?我dlv 调试看到的调用流程都是一样的
  26. 26. select的实现原理(channel的)
  27. 27.go语言为什么没有选择使用 分代回收 以及标记压缩来优化GC。
  28. 28.slot可以简单的理解为老指针对象吗?ptr就是新指向的对象。 slot字面上理解是内存上的槽。。举个例子:A=&B,曹大能说一下哪个是slot哪个是ptr吗。
  29. 29.能简单描述下多个gc线程跑的时候是怎么解决不同gc
  30. 30.线程冲突的问题吗?不会同时两个gc扫描同一个内存吗?
  31. 31.混合屏障相对 Yuasa屏障的优势就是 不需要GC开始时的STW对吧?那为什么 Yuasa的删除写屏障则需要在GC开始时STW扫描堆栈来记录初始快照?
  32. 32.混合屏障相对于Dijsktra屏障的优势是不需要Rescan,而Rescan是因为在栈上创建的对象为白色造成的,所以混合屏障中创建的对象都为黑色。那么Dijsktra+栈上对象标黑就能完成,为什么还需要Yuasa屏障。
  33. 33.混合写屏障是所有栈、堆新创建的对象都会全部标黑吗?既然堆上的对象都是有写屏障,那创建时为什么还要标黑呢?
  34. 34.全局变量是不是永远不会被gc回收?
  35. 35.之前面试被问 无锁队列和有锁数据结构的实现,面试官说 无锁队列 对 CPU 不友好,是真的嘛
  36. 36.是的,大部分要自旋
  37. 37.以下这个问题这样回答可以吗?有没有错误或修正的地方?
  38. 怎样保证Cache和DB的数据的一致性?
    1. 如果是普通缓存(如in-process localcache):延迟双删 + 消息队列
  39. 如果是Redis作为缓存:SetEX/NX + 消息队列
  40. 38.有人说stw可以完全去除可信吗?
  41. 39.gc线程和用户线程是并发的话,那么gc对用户线程的影响只是在stw时才能让用户感知到吗?
  42. 40.我用dlv调试的时候 发现runtime.g0和runtime.m在一开始就有值了 那这个是什么时候复值的?刚开始的g0主要负责什么呀?
  43. 41. m0上只跑g0,那g0上运行的main.main里面如果执行了 time. sleep 那这个m0也只会阻塞在这么 而不是运行其他的g么
  44. 42.gc在什么时候讲标记的对象复原。是不是每次gc周期结束就会讲标记的颜色清空。
  45. 43.曹大线上调试工具分享下呀
  46. 58.线上可以开 pprof 嘛

1.gc时扫描栈区是不是只有 检查有没有栈区的对象指向堆区对象 这一个作用?栈区在函数调用结束时会自动回收函数占用的空间,是否代表函数占据的空间理论上不需要gc这种算法去做垃圾回收?

  • goroutine stack 本身占的内存 allocManual、freeManual
  • goroutine stack 上面的变量要参与 GC,是因为栈上对象可能有指向堆上的对象的指针。

2.GMP有的人说1/61并不是每隔60次去全局队列中找,而是每次都1/61的概率去全局队列中找,哪个对呢?

3.Go1.8之后的混合写屏障,怎么具体防止了 黑色新指向白色且被灰色不可达 导致的数据丢失?混合写屏障只优化了重新扫描栈,但没有优化延迟清理?

  • 动画看一下~
  • 延迟清理没有解决,标记期间新生成的对象都是黑色的,还是要等下一个 GC 周期扫描和 sweep

4.如果说逃逸分析是编译时的,但是我在占上分配一个运行时才能确定长度的slice,那逃逸分析是会被无效么?

  • make([]int, os.Args[1]) => escape

5.怎样理解 Happens Before?

  • 并发,memory barrier,load acq, store rel 概念太底层,应用程序员不好理解,所以为让应用程序员更好理解,抽象了一层,memory model。synOnce,do 之后,happen before 的保证。

6.m0主要做了什么事情。m0和其他m区别么

  • 主线程 => runtime.main,m0 只能执行主线程的代码,退出后整个进程退出

7.channel的实现原理,直接拷贝 发生在什么时候?

  • chan.go 搜索 direct

8.defer的实现原理,以及开放编码是怎么回事?

9.链表对GC不友好,这句话对吗?

  • 链表指针多,确实对 gc 不友好

10.进入gc.markDone()时是已经标记完成了吗,然后再进入gcMarkTermination进行sweep吗? 还有Yuasa感觉会产生浮动垃圾,g1收集器好像也是Yuasa,它好像快照完,所有快照的引用不管是不是垃圾都不回收,然后下次再回收,导致有浮动垃圾

  • 是的,就差 wbBuf 里的一些剩余工作,清空后就可以进 termination 了
  • gcSweep –wake–> (sweep.g –> sweep)
  • 后半句稍微有点没看懂,skip,微信群或者问答区说

11.为什么栈上开写屏障开销高?

  • 因为栈上的变量操作频率高,goroutine 数量大

12.go 的map什么时候等量扩容?PPt看了又不理解了。

13.error类型是小写,为啥可在其他包中引用?看到书里说是预定义标识符,是全局块的一部分

14.曹大,channel调试的流程能简单演示一下吗

  • 看一下 1,2 课的答疑

15.fatal error 错误 写测试的 时候是不是没有办法抓到处理?

  • os.Exit()
  • 捕捉不了

16.gc的触发时机,runtime.mallocgc,不太理解

  • mallocgc 分配内存触发

17.GMP, g和m分别有具体的结构体,那p具体在源码上是什么呢?

  • type p struct

18.程序刚启动,main.main作为主goroutine怎么绑定P,g0怎么工作,以及在main函数里go func,怎么新启动M和偷窃、调度?

  • procresize 绑定了 p
  • newproc, mstart

19.os.Exit不会执行defer,是不会执行子goroutine的defer、只会调用main函数的的defer对吗?那子goroutine里面调用函数的defer怎么才能正常执行到呢?kill哪个命令对应的是os.Exit?

20.cgo 代码如何调试?怎么捕获内存分配信息

21.现在想准备跳槽,系统方面有什么书可以推荐,go的课程信心挺足,系统方面都没头绪,不知道怎么准备,目标公司B站

  • system design primer, grokking system design
  • kratos, overlord
  • 八股文,redis,mysql,mq,面向对象设计 solid,clean architecture

23.蚂蚁线上一个服务是几个pod做负载均衡?

23.现在工作一两年的面试已经八股文全覆盖了,工作年限再高一些问啥?

24.面试有问为什么要内存对齐,和高速缓存有什么关系。

  • CPU 从内存里读数据,按八字节对齐会快一些
  • 内存填充 pad,avoid false sharing => cache bouncing
  • unsafe.Alignof
  • structlayout, linter

25.a:=make([]*Person,0,0) 和 a:=[]*Person{} 这两种分配有区别吗?我dlv 调试看到的调用流程都是一样的

  • var a []*Person, 如果后续没用到 a,那就不需要分配内存。题目中的两种写法是一定会分配内存
  • a:=make([]*Person,0,0) ===== a:=[]*Person{}
  • a := []byte{} escape, cap changed

26. select的实现原理(channel的)

  • skip

27.go语言为什么没有选择使用 分代回收 以及标记压缩来优化GC。

28.slot可以简单的理解为老指针对象吗?ptr就是新指向的对象。 slot字面上理解是内存上的槽。。举个例子:A=&B,曹大能说一下哪个是slot哪个是ptr吗。

  • slot = 老指针,*slot = 指向的老对象,ptr 新的指针/对象
  • A = slot,&B = ptr

29.能简单描述下多个gc线程跑的时候是怎么解决不同gc

30.线程冲突的问题吗?不会同时两个gc扫描同一个内存吗?

  • 对象根遍历起始的时候用 atomic + 1 避免标到同一个根
  • 理论上应该有可能,需要看一下代码,问答区见

31.混合屏障相对 Yuasa屏障的优势就是 不需要GC开始时的STW对吧?那为什么 Yuasa的删除写屏障则需要在GC开始时STW扫描堆栈来记录初始快照?

32.混合屏障相对于Dijsktra屏障的优势是不需要Rescan,而Rescan是因为在栈上创建的对象为白色造成的,所以混合屏障中创建的对象都为黑色。那么Dijsktra+栈上对象标黑就能完成,为什么还需要Yuasa屏障。

33.混合写屏障是所有栈、堆新创建的对象都会全部标黑吗?既然堆上的对象都是有写屏障,那创建时为什么还要标黑呢?

  • GC 期间创建的对象如果是白色的,那 GC mark 完成后,还需要对这些新对象做扫描
  • 标黑为了让这个对象,这个周期不要参与 GC,延迟到下一个 GC 周期扫描和回收
  • 简化算法

34.全局变量是不是永远不会被gc回收?

  • 是的
  • 全局对象也是根对象的一种

35.之前面试被问 无锁队列和有锁数据结构的实现,面试官说 无锁队列 对 CPU 不友好,是真的嘛

36.是的,大部分要自旋

  • for {} runqput,runqget

37.以下这个问题这样回答可以吗?有没有错误或修正的地方?

怎样保证Cache和DB的数据的一致性?

  • 数据不一致的情况举例:先读Cache, CacheMiss, 再读DB,准备要构建Cache时,DB被更新,并更新Cache,然后才执行前面的构建Cache,导致Cache中数据为旧数据

如果是普通缓存(如in-process localcache):延迟双删 + 消息队列

  • DB被更新时,先删除Cache,再更新DB
  • DB(MySQL)使用canal订阅binlog并推送到消息队列
  • 再删除Cache
  • 等待超过 读业务读Cache的处理时间 后,消费消息队列数据并重新更新Cache

如果是Redis作为缓存:SetEX/NX + 消息队列

  • 也可以使用延迟双删,但Redis提供了锁的命令可用,即:DB主动更新时,更新缓存用SETEX命令,即使存在也刷新;CacheMiss构建缓存时,使用SETNX命令,不存在才更新
  • 上述不一致场景中,先读Cache, CacheMiss, 再读DB,准备要构建Cache时,DB被更新,并使用SETEX更新Cache,然后才执行使用SETNX构建Cache,因为已经存在不执行,Cache中即为新数据
  • DB被更新还是要使用消息队列做兜底,因为更新Cache的命令也可能执行不成功

38.有人说stw可以完全去除可信吗?

  • 不太确定。。。。

39.gc线程和用户线程是并发的话,那么gc对用户线程的影响只是在stw时才能让用户感知到吗?

  • 用户 goroutine 分配内存会做协助标记assist,这部分会对你的延迟产生影响

40.我用dlv调试的时候 发现runtime.g0和runtime.m在一开始就有值了 那这个是什么时候复值的?刚开始的g0主要负责什么呀?

  • m0.g0 -> runtime 里的代码
  • m0 赋值去问答区吧

41. m0上只跑g0,那g0上运行的main.main里面如果执行了 time. sleep 那这个m0也只会阻塞在这么 而不是运行其他的g么

  • m0 上不是只跑 g0,main.main 有单独的 goroutine
  • m0 不会执行其它的 goroutine,有一个 LockOsThread 的过程,详情问答区

42.gc在什么时候讲标记的对象复原。是不是每次gc周期结束就会讲标记的颜色清空。

  • 找一下 gcmarkbits 修改位置,代码位置去问答区问
  • 下一轮 gc 标记开始前,要保证 gcmarkbits 都是空的

43.曹大线上调试工具分享下呀

  • pprof,+ 日志,ebpf(坑)

58.线上可以开 pprof 嘛


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 lihuanjie113@gmail.com

×

喜欢就点赞,疼爱就打赏