3.那些神奇的内置数据结构

  1. notesleep/notetsleep的作用是什么
  2. 如何打包的sudog
  3. sysmon和m0的联系是什么
  4. sysmon兜底做了什么
  5. semaphore会详细讲下么?因为我在ppt里面只看到提了一下。
  6. 怎么将panic像error一样捕获并带上上下文
  7. sql.nullstring,sql.nullint 等类型的json 去除valid 怎么实现 在json的类型上怎么改
  8. chan(chan int)与chan(chan int,0)有区别吗
  9. channel能实现无锁化设计吗?
  10. 如果讲课时间有限制,可以在PPT内多提供些课外内容,我们其他时候看哈。
  11. 无缓冲channel的发送与接收有什么优化吗?
  12. chan的数据结构,因为Lock的原因,在同一时刻sendq和recvq只有一个属性是not empty
  13. sendq、recvq能存多大的数据?
  14. chansend cannot send不能发送是什么意思?
  15. 一般环形队列都是可以使用atomic.CAS来进行无锁处理的,为什么channel不使用,而要加全局lock呢?atomic.CAS有什么缺陷吗?
  16. chan里的lock和mutex有什么区别? 不一样的话,chan里的lock为什么不直接使用mutex? chan里的lock为什么不暴露给用户呢?
  17. gopark挂起的时候,就是 当前运行的M会保存这个G的上下文吗?
  18. goready中会调用systemstack,goroutine恢复执行,需要这个函数找到对应sudog里面g的栈吧?这个函数是汇编实现吗?
  19. 单个四插堆时候的timer的loop check时间间隔是多少?
  20. 可以在timer源码上带讲一下实现原理吗,不结合源码看总感觉很虚
  21. 为什么要使用四叉堆,而不是用二叉堆或五叉堆等?
  22. 为什么要把所有的timer维护到一个p个数的数组里?而不是每个p维护一个自己的四叉堆就行?
  23. 请问哪些任务是计算密集型?
  24. timerproc在goroutine执行的时候会因为goroutine的公平性延迟执行吗?
  25. channel 队列为什么要使用环形链表保存
  26. 打包成sudog也算一个变相的缓冲区吧,那跟多加一个缓冲有啥区别,都是会变成待执行。
  27. atomic和mutex分别在什么情况下用会比较好,channel用的是mutex吗?
  28. make(chan struct{})记得有文档说有特殊优化,譬如分配内存少,不实现直接发送给recv方等,是否还有其它优化?
  29. map 的 “桶” 和overflow桶,nex。是怎么的关系
  30. 同事说,从map检查数据是否存在没有从slice中检查快,数据量少的时候我觉得没啥
  31. map什么时候在栈上什么时候在堆上创建
  32. 是不是每次map扩容,就要对所有的bucket重新分配一遍阿?
  33. mapdelete为什么需要顺手搬运,而不是直接删除?
  34. golang的map不会缩容,所以手动缩容需要把内容从map a手动放到map b,这种情况在生产情况下有影响吗?是否有更佳的解决方案?
  35. 尾部hash确定桶,头部hash确定桶中的位置,如果冲突了就放进overflow吗? 那是否有某个桶5个元素,5个元素的头尾hash均相同,则会有5层bmap - 4层overflow)?
  36. 既然有bucket的overflow机制,为啥要还有搞多个bucket
  37. map(预分配一大片内存)存了不少东西 重启进程后数据不丢, 有办法吗?
  38. 涉及到并发map+lock和sync.Map如何选择? 应该是大部分场景下使用map+lock吗?
  39. 等长扩容没听明白,什么场景下不用B+1?
  40. context能不能放在struct上,不作为参数
  41. 什么情况下用context WithValue传递值。而不直接通过参数传递值。用Context.WithValu传递值有什么好处。
  42. 面试题:time.now返回的是什么时间?
  43. map读写为什么是并发不安全的
  44. sync.map的性能与加lock相比如何
  45. 数据倾斜、hash 碰撞攻击

notesleep/notetsleep的作用是什么

  • 问答区提吧,需要粘代码来说

如何打包的sudog

  • 看一下 chansend 或 chanrecv 函数在 gopark 前面,acquireSudog 后面的代码,比较短小

sysmon和m0的联系是什么

  • 参考第一课的 ppt

sysmon兜底做了什么

  • 问答区提吧~

semaphore会详细讲下么?因为我在ppt里面只看到提了一下。

  • 会讲,下一节课或者同步编程中会说

怎么将panic像error一样捕获并带上上下文

  • pkg/errors errors.Wrap

  • 比较难用

sql.nullstring,sql.nullint 等类型的json 去除valid 怎么实现 在json的类型上怎么改

  • 之前待过的公司,基本上数据库规范都会对 null 的类型做约束,较少碰到这些问题

chan(chan int)与chan(chan int,0)有区别吗

  • 没区别

channel能实现无锁化设计吗?

  • 能,消耗 CPU
  • 所以有锁和无锁设计是在 CPU 还是内存之间作了一个权衡

如果讲课时间有限制,可以在PPT内多提供些课外内容,我们其他时候看哈。

  • 可以,下次我多贴一些

无缓冲channel的发送与接收有什么优化吗?

  • 看一下 dataqsize == 0 的几个 if 判断

chan的数据结构,因为Lock的原因,在同一时刻sendq和recvq只有一个属性是not empty

  • 没看懂,skip,问答区重新描述一下吧

sendq、recvq能存多大的数据?

  • 链表,理论上内存够就可以一直链下去

chansend cannot send不能发送是什么意思?

  • 需要修正一下 ppt

  • 已补充 cannot 的细节

一般环形队列都是可以使用atomic.CAS来进行无锁处理的,为什么channel不使用,而要加全局lock呢?atomic.CAS有什么缺陷吗?

  • cas 和 for 循环结合使用,耗 CPU

  • 这里是并发编程时的一种权衡

chan里的lock和mutex有什么区别? 不一样的话,chan里的lock为什么不直接使用mutex? chan里的lock为什么不暴露给用户呢?

gopark挂起的时候,就是 当前运行的M会保存这个G的上下文吗?

  • M -> gopark,g -> sendq(g 现场 -> g.gobuf),M -> schedule

  • 现场是在 g 的 gobuf 结构中保存的,M 负责运行保存代码,但内容不是保存在 M 的

goready中会调用systemstack,goroutine恢复执行,需要这个函数找到对应sudog里面g的栈吧?这个函数是汇编实现吗?

  • 汇编函数,问答区

单个四插堆时候的timer的loop check时间间隔是多少?

  • 按堆顶到期时间来 sleep。

可以在timer源码上带讲一下实现原理吗,不结合源码看总感觉很虚

  • 源码解析看 reference

  • 我想了想,这个可以答疑课来讲讲

为什么要使用四叉堆,而不是用二叉堆或五叉堆等?

  • 个人觉得 4 叉堆(空间)局部性好一些

  • 一般数据结构设计还是 2 的整数倍多一些。。

为什么要把所有的timer维护到一个p个数的数组里?而不是每个p维护一个自己的四叉堆就行?

  • 下一页PPt讲到了。。。…

请问哪些任务是计算密集型?

  • bcrypt
  • ffmpeg
  • json.Unmarshal

timerproc在goroutine执行的时候会因为goroutine的公平性延迟执行吗?

  • 有很多相关的 issue,可以翻翻

channel 队列为什么要使用环形链表保存

  • 不用环形队列就得扩容了

打包成sudog也算一个变相的缓冲区吧,那跟多加一个缓冲有啥区别,都是会变成待执行。

  • 有 buffer 的 channel,没法预料洪峰的时候会有多少个 goroutine 阻塞。

atomic和mutex分别在什么情况下用会比较好,channel用的是mutex吗?

  • 尽量 mutex

  • 一些比较简单的场景,比如:

    • 配置加载双 buffer,可以用 atomic。
    • 并发安全计数器,可以用 atomic
  • atomic 相对来说是比较底层的 API,应用层还是尽量少用~除非在锁有明显的性能瓶颈时,需要考虑优化。

make(chan struct{})记得有文档说有特殊优化,譬如分配内存少,不实现直接发送给recv方等,是否还有其它优化?

  • 问答区

map 的 “桶” 和overflow桶,nex。是怎么的关系

  • ppt后面,在发生 hash 冲突时,溢出元素会放进溢出桶里,一直向后链

  • nextoverflow 指向下一个空闲的 overflow bucket,只在预留的 overflow bucket 没用完的时候有用。用完了以后,新的 overflow bucket 分配就都走堆分配了

同事说,从map检查数据是否存在没有从slice中检查快,数据量少的时候我觉得没啥

  • map[int64]struct{}这样的结构

  • go test -b. = benchmark,要用 benchmark 来说话,别人说的都不靠谱

map什么时候在栈上什么时候在堆上创建

  • 逃逸分析的结果,可以用 go build -gcflags=”-m” 来查看

是不是每次map扩容,就要对所有的bucket重新分配一遍阿?

  • 是的

mapdelete为什么需要顺手搬运,而不是直接删除?

  • 命中的只是 bucket 中的一个元素(entry),一个 bucket 里有 8 个元素
    删除也只是删除一个 bucket 中 8 个元素的其中一个,不是把 bucket 全给删了

golang的map不会缩容,所以手动缩容需要把内容从map a手动放到map b,这种情况在生产情况下有影响吗?是否有更佳的解决方案?

  • 有影响

  • 暂时没有好解决办法,有的团队会改 runtime 代码,搞定制版 runtime,比如专门给 map 提供一个 shrink 的 API

尾部hash确定桶,头部hash确定桶中的位置,如果冲突了就放进overflow吗? 那是否有某个桶5个元素,5个元素的头尾hash均相同,则会有5层bmap - 4层overflow)?

  • 没太看懂。。skip,问答区

既然有bucket的overflow机制,为啥要还有搞多个bucket

  • 哈希表的设计原则一定是希望 overflow 尽量少,整体的 bucket 平铺开,这样时间复杂才是 O(1)

  • 如果只有一个 bucket,其它的都在 overflow 上,那元素的查询时间复杂度就不是常数 O(1),而是 O(elem_count) 了

map(预分配一大片内存)存了不少东西 重启进程后数据不丢, 有办法吗?

  • nvm optane,Go 有一个 proposal 是讲这个的,不过也只是个实验,短期好像看不到合并到 master 的可能性

  • 预知详情问答区说

涉及到并发map+lock和sync.Map如何选择? 应该是大部分场景下使用map+lock吗?

  • 一般无脑用 sync.Map 方便一些

  • 但 sync.Map API 不友好,interface{} 很恶心,未来有泛形应该会好很多

  • 还有一种场景,map 不会做元素更新,只会做整体替换的,这种使用普通 map 比 sync.Map 好

等长扩容没听明白,什么场景下不用B+1?

  • load factor 还没到太大,但是 overflow bucket 有点多,尽量拍平了

context能不能放在struct上,不作为参数

什么情况下用context WithValue传递值。而不直接通过参数传递值。用Context.WithValu传递值有什么好处。

  • ctx 传送值好处,不需要改函数签名。

  • 但值进入 ctx 后变为隐式传递,对代码读者不友好,所以尽量放 request_id,trace_id,span_id,和其它有共识的业务字段。否则你的项目的后续维护者一定会骂你的。

  • 不要放太多参数

面试题:time.now返回的是什么时间?

  • 问答区

map读写为什么是并发不安全的

  • int 读写都是并发不安全的

sync.map的性能与加lock相比如何

  • 这是我们这次的作业之一。。。。

数据倾斜、hash 碰撞攻击

  • hmap.hash0 是为了避免数据倾斜、hash 碰撞攻击的一个 hash seed,可以看看它是怎么用的

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

×

喜欢就点赞,疼爱就打赏