摘要:
客户端日志系统 使用场景 用户通过app store下载app后, 在使用过程中出现了异常情况, 例如 功能异常等. 例如BugHD 会自动捕获崩溃信息, 但开发人员想重现是不容易的. 设计方案 一. 收集 log模块化,暴露接口, 对日志分级, info, debug(支持打印类似 NSLog), 阅读全文
摘要:
网络基础 协议架构 tcp链接 假如需要开发者去实现一套新的网络协议(例如 redis 的resp), 是基于TCP的, 那tcp这层的协议,是否需要开发者自己去实现? 这层如果自己实现, 其实很复杂, 会涉及很多算法相关. 因此, 出现了 socket 对传输层进行了抽象, 开发者不需要关注传输层 阅读全文
摘要:
垃圾回收 (Garbage Collecting)思路 1. "标记-清除〞 go的做法 2. "标记-整理〞 标记后删除, 删除后重新把内存空间整理 java 早期 3. "标记 - 复制〞 两块相似的内存, 直接把有用的拷贝到另外一块上去 java 现阶段 Go因为堆内存结构的独特优势,选择最简 阅读全文
摘要:
协程栈 go 栈的位置 1. Go 协程栈位于 Go-堆内存上 2. Go 堆内存位于操作系统虚拟内存上 go 栈的工作流程 以main.main为出发点 要记录runtime.main的栈基地址 记录 a 和 b的局部变量值 开辟一个空间记录 sum函数的返回值 记录 b 和 a的值, 这里是为了 阅读全文
摘要:
模型 三部分组成: 发送等待队列 接收等待队列 管道 缓存区 定义 在 runtime 的chan.go中 type hchan struct { qcount uint dataqsiz uint buf unsafe.Pointer elemsize uint16 elemtype *_type 阅读全文
摘要:
go读写锁 互斥锁每次只让一 g通过,去读写数据。但是读数据操作,并发其实没有问题。所以诞生了 读写锁。 读协程可以并发,一起读。但是 写协程还是要走互斥锁,只能一个个通过。 先加了读锁 先加了读锁。那么写的协程,就需要去休眠队列中等待。一直到读锁都释放。 先加了写锁 这个时候,不管再来 写协程还是 阅读全文
摘要:
互斥锁的定义 type Mutex struct { state int32 sema uint32 } 一个 sema,背后实际上 是一个 休眠队列,可以看下上篇。 一个state,这个状态 分为4个部分。 后三位 各自代表一个状态。 前29位代表最大可等待协程的个数。 state的结构 lock 阅读全文
摘要:
atomic和sema是实现go中锁的基础,简单看下他们的实现原理。 atomic atomic 常用来作为保证原子性的操作。 当多个协程,同时一个数据进行操作时候,如果不加锁,最终的很难得到想要的结果。 var p int64 = 0 func add() { p = p + 1 } func m 阅读全文
摘要:
当m在执行某个g的时候,g非常耗时,例如一个for循环,每次循环sleep1分钟,循环1000次。 这个例子看似无聊,却是很难解决的,成功的避开了2个系统切换时机。 如果这个时候,一直执行这个g,别的g就会得不到执行,例如有g是处理用户支付的,这样就会造成收钱不积极。 协程饥饿问题 本地队列 本地队 阅读全文
摘要:
go的协程和线程都绕不过GMP,关于GMP基本的工作流程,有go开发经验的大致都懂,这边更多关注GMP如何解决一些类似 协程饥渴的问题,以及底层的大致实现原理。 多线程循环 上篇讲了单线程是如何循环的,这里还是为 GMP的出场 大致介绍下。 工作模型 多个M都去全局G的队列中获取 g,所以,全局g的 阅读全文