https://github.com/panjf2000/ants/blob/master/README_ZH.md

  1. 性能测试做的很全面,具体方法总结

  2. 接口定义清晰,同时 demo 结合 defer 做资源释放

    2.1. Submit、NewPoolWithFunc、Invoke、Release

    2.2. Options -> WithXXArgOptions

  3. 使用文档清晰全面,同时还有运行时流程图

  4. 单元测试集中在 ants_test.go 文件,面向应用的行为(接口)在测试

优秀代码片段

  1. 自动设置 Pool 是阻塞的还是非阻塞的,防止单核频繁切换 Goroutine 调度:Inspired by fasthttp at https://github.com/valyala/fasthttp/blob/master/workerpool.go#L139
workerChanCap = func() int {
		// Use blocking workerChan if GOMAXPROCS=1.
		// This immediately switches Serve to WorkerFunc, which results
		// in higher performance (under go1.5 at least).
		if runtime.GOMAXPROCS(0) == 1 {
			return 0
		}

		// Use non-blocking workerChan if GOMAXPROCS>1,
		// since otherwise the Serve caller (Acceptor) may lag accepting
		// new connections if WorkerFunc is CPU-bound.
		return 1
	}()
  1. 使用 atomic 原子操作代替锁,优点是啥?性能更高?
type spinLock uint32

func (sl *spinLock) Lock() {
	for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
		runtime.Gosched()
	}
}

func (sl *spinLock) Unlock() {
	atomic.StoreUint32((*uint32)(sl), 0)
}

// NewSpinLock instantiates a spin-lock.
func NewSpinLock() sync.Locker {
	return new(spinLock)
}
  1. Goroutine 内存提前申请分配,有循环队列和栈两种管理类型
if p.options.PreAlloc {
		p.workers = newWorkerArray(loopQueueType, size)
} else {
		p.workers = newWorkerArray(stackType, 0)
}

loopQueueType 循环队列(维护首尾指针)提前分配好了内存,性能高

stackType 是一个可扩展长度的池(slice),每次从队尾获取/插入 Goroutine,节约内存;用二分查找来寻找过期的 Goroutine

  1. 使用 sync.Pool 来加速获取在运行的 worker,sync.Pool 是干啥的? 存储运行中的 Goroutine ?

博客:https://juejin.im/post/5d4087276fb9a06adb7fbe4a

  1. workerArray 是存储已经申请的 Goroutine (不是在运行中的)进行池化,重复利用?

    5.1. insert 插入空闲 Goroutine 到 workerArray

    5.2. detach 从 workerArray 获取可用的 Goroutine


更多精彩请扫码关注如下公众号。