垃圾回收不是万能的,Go 一样存在资源泄露问题。 1. SetFinalizer虽然垃圾回收器能很好地处理循环引用,可一旦加上 SetFinalizer,事情就不那么美妙了。 显然,这些对象并未被释放。在标准库文档里有这样的描述:
好在这类状况并不常见,SetFinalizer 最大的问题是延长了对象生命周期。在第一次回收时执行 Finalizer 函数,且目标对象重新变成可达状态,直到第二次才真正 “销毁”。这对于有大量对象分配的高并发算法,可能会造成很大麻烦。
2.Goroutine Leak无论是同步通道(channel),还是带缓冲区的异步通道。当条件不满足时,都会进入等待队列休眠,直到被另一方唤醒。可如果没有被唤醒,那么会出什么问题? 这是个极简单的演示,我们注释掉数据读取方,让发送方全部进入休眠等待状态。按理说,当 test 执行结束后,通道 c 已超出作用域,理应被释放回收,但实际情况是: 这些处于 “chan send” 状态的 G 对象(goroutine)会一直存在,直到唤醒或进程结束,这就是所谓的 “Goroutine Leak”。解决方法很简单,可设置 timeout。或定期用 runtime.Stack 扫描所有 goroutine 调用栈,如果发现某个 goroutine 长时间(阈值)处于 “chan send” 状态,可用一个类似 “/dev/null hole” 的接收器负责唤醒并 “处理” 掉相关数据。 任何机制都有覆盖不到的地方,这就要求我们对底层的某些实现方式有所了解,同时进行严格测试。 最新动态,请扫码关注 |
|
来自: javenpop > 《Go性能优化技巧》