众所周知,goroutine 是同步但非阻塞的处理单元。golang 调度器很好地处理了非阻塞任务,例如套接字、定时器、信号或来自字符设备的其他事件。
但是块设备 io 或 CPU 敏感任务呢?它们在完成之前不能被中断,也不能被多路复用。运行 goroutine 的 OS 线程将冻结,直到 goroutine 返回或让步。在这种情况下,调度粒度变差。
当然,你可以在你的代码中将任务拆分成更小的子任务,例如,不要一次复制 1GB 的文件,而是先复制 10MB,然后再复制 10MB 等,以便其他 goroutine 在相同的操作系统线程有机会运行。CPU 密集型任务的另一个示例:部分压缩文件并最终合并它们。
但这破坏了顺序编程的便利性,与OS线程上的OS调度相比,手动调度难以均匀估计。
nginx 也有类似的问题,它是多进程程序,一个 CPU 核一个进程,类似于 GOMAXPROCS 的最佳实践。它引入线程池来处理阻塞任务。也许它对 golang 也有好处。我很好奇为什么golang没有OS线程API,这对于阻塞任务的goroutine应该是很好的补充。
临摹微笑
相关分类