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为什么不暴露给用户呢?
- runtime 有自己的 mutex 实现
- https://colobu.com/2020/12/06/mutex-in-go-runtime/
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上,不作为参数
这个事情:https://blog.golang.org/context-and-structs,在这篇 blog 里说不要嵌
什么情况下用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