wangwangwar / daily-notes

Daily Notes
4 stars 0 forks source link

IO密集型操作与CPU密集型操作 #35

Closed ButtFly closed 7 years ago

ButtFly commented 9 years ago

这是一个相对概念,如果你的操作大部分时间都是在等待I/O,CPU长时间处于挂起状态,那么可以说你现在的操作是I/O密集型操作,CPU密集型则是相反。当然这既然是一个相对概念,那么就要视现在的情况而定。如果你的CPU性能不好,大多数时间都很忙,那么就是CPU密集型;这时候你换了一个强大的CPU,大大加强了CPU的计算能力,这个时候CPU大多数时间就是很闲的,也就完成了CPU密集型向I/O密集型的转化。

当然,从现在的情况来看,我们的大部分操作可以算作是I/O密集型操作,有限制的数据传输速度和强大的计算能力。App可以看作是内存与CPU,服务端可以看作宽带带宽与CPU。

wangwangwar commented 9 years ago

Register -> L1/L2/L3 Cache -> Memory -> Disk -> Network,越靠近CPU,存储速度越快,同时价格也越昂贵(相应容量也越小)。 从速度来说,比如Register的存储速度是和CPU的单条指令相同的(因为存取Register只需要一条指令),比如设为1ns,那么L1 Cache的速度大概在几ns,Memory的速度大概就是几百ns,Disk的速度是几百ms,Network那就是几s了。 从容量来说,Register相当有限,大概就几百B,L1 Cache大概几十KB,Memory几G,Disk几T,Network那就接近无限了。

最理想的硬件条件无疑是同时拥有Register的速度和Network的容量(价格)。当然这是不可能的,所以我们需要折中。现在流行的方式就是使用Cache。无论制造硬件还是编写程序,Cache无处不在:

  1. 硬件上来说,Memory中的数据在读取到Register中时,会同时更新L1/L2/L3 Cache,L1/L2/L3 Cache就是Memory的一个Cache。有如硬盘一般会内置几M的内存,这也是对硬盘的一个Cache。
  2. 软件上来说,我们经常会把从Network取到的数据,缓存到本地或者内存,这是一种Cache,从磁盘读取数据到内存反复使用,这是一种Cache,那怕是程序中将运算过程中的中间变量存在一个临时变量中(比如加速版的Fibonacci数列计算)这也是一种Cache。

回到最初的讨论,如果我们定义I/O密集型操作为读取硬盘或者访问网络,其操作离CPU的距离太远,导致CPU不得不等待数据取回,记住,Disk的速度是ms级别,CPU的速度是ns级别,1ms = 1e6ns,也就是说,在Disk返回数据时CPU空转了几百万次,这绝对是巨大的浪费。

所以,一切的手段,都是为了让CPU更忙碌一点。多进程,多线程,基于事件,回调,都是为了在等待数据的时候,让CPU去干更有意义的事情而不是空转。