• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Go 性能优化技巧 10/10

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

垃圾回收不是万能的,Go 一样存在资源泄露问题。


1. SetFinalizer

虽然垃圾回收器能很好地处理循环引用,可一旦加上 SetFinalizer,事情就不那么美妙了。

显然,这些对象并未被释放。在标准库文档里有这样的描述:

Finalizers are run in dependency order: if A points at B, both have finalizers, and they are otherwise unreachable, only the finalizer for A runs; once A is freed, the finalizer for B can run. If a cyclic structure includes a block with a finalizer, that cycle is not guaranteed to be garbage collected and the finalizer is not guaranteed to run, because there is no ordering that respects the dependencies.

好在这类状况并不常见,SetFinalizer 最大的问题是延长了对象生命周期。在第一次回收时执行 Finalizer 函数,且目标对象重新变成可达状态,直到第二次才真正 “销毁”。这对于有大量对象分配的高并发算法,可能会造成很大麻烦。

SetFinalizer sets the finalizer associated with x to f. When the garbage collector finds an unreachable block with an associated finalizer, it clears the association and runs f(x) in a separate goroutine. This makes x reachable again, but now without an associated finalizer. Assuming that SetFinalizer is not called again, the next time the garbage collector sees that x is unreachable, it will free x.


2. Goroutine Leak

无论是同步通道(channel),还是带缓冲区的异步通道。当条件不满足时,都会进入等待队列休眠,直到被另一方唤醒。可如果没有被唤醒,那么会出什么问题?

这是个极简单的演示,我们注释掉数据读取方,让发送方全部进入休眠等待状态。按理说,当 test 执行结束后,通道 c 已超出作用域,理应被释放回收,但实际情况是:

这些处于 “chan send” 状态的 G 对象(goroutine)会一直存在,直到唤醒或进程结束,这就是所谓的 “Goroutine Leak”。解决方法很简单,可设置 timeout。或定期用 runtime.Stack 扫描所有 goroutine 调用栈,如果发现某个 goroutine 长时间(阈值)处于 “chan send” 状态,可用一个类似 “/dev/null hole” 的接收器负责唤醒并 “处理” 掉相关数据。

任何机制都有覆盖不到的地方,这就要求我们对底层的某些实现方式有所了解,同时进行严格测试。




最新动态,请扫码关注





转载于:https://my.oschina.net/qyuhen/blog/670307


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Ubuntu系统下Maix Go在minicom中无法输入命令的问题发布时间:2022-07-10
下一篇:
go语言编程小游戏--贪吃蛇发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap