其他
协程究竟比线程牛在什么地方?
高并发:每秒钟需要处理成千上万的用户请求 周期短:每个用户处理耗时越短越好,经常是ms级别的 高网络IO:经常需要从其它机器上进行网络IO、如Redis、Mysql等等 低计算:一般CPU密集型的计算操作并不多
func cal() {
for i :=0 ; i<1000000 ;i++{
runtime.Gosched()
}
}
func main() {
runtime.GOMAXPROCS(1)
currentTime:=time.Now()
fmt.Println(currentTime)
go cal()
for i :=0 ; i<1000000 ;i++{
runtime.Gosched()
}
currentTime=time.Now()
fmt.Println(currentTime)
}
# cd tests/test05/src/main/;
# go build
# ./main
2019-08-08 22:35:13.415197171 +0800 CST m=+0.000286059
2019-08-08 22:35:13.655035993 +0800 CST m=+0.240124923
在空间上,协程初始化创建的时候为其分配的栈有2KB。而线程栈要比这个数字大的多,可以通过ulimit 命令查看,一般都在几兆,作者的机器上是10M。如果对每个用户创建一个协程去处理,100万并发用户请求只需要2G内存就够了,而如果用线程模型则需要10T(下面图片可能需要左右拖动)。
# ulimit -a
stack size (kbytes, -s) 10240
扩展:由于go的协程调用起来太方便了,所以一些go的程序员就很随意地go来go去。要知道go这条指令在切换到协程之前,得先把协程创建出来。而一次创建加上调度开销就涨到400ns,差不多相当于一次系统调用的耗时了。虽然协程很高效,但是也不要乱用,否则go祖师爷Rob Pike花大精力优化出来的性能,被你随意一go又给葬送掉了。