分层与封装(3) 计算机系统的性能
按照著名的短板理论,一个木桶能装水的容量取决于最短的木板。所以想当然的可以认为,计算机系统的效率取决于系统最慢的一部分。这看上去是正确的,首先回顾下计算机被分成了三层,最底层的硬件、中间层的操作系统和最上层的应用。计算机的速度当然是被其中最慢的一层决定的,如果应用慢,那么再好的硬件和操作系统也不会快多少;如果硬件慢,那么再好的应用和操作系统也不会变得快。这种分层的思路给了我们分析系统效率的一个途径,但是实际情况比这个复杂很多。
考虑一个简单的没有显示和声音设备的计算机,他的功能只有计算和读写硬盘。那么这个计算机系统的效率取决于什么呢?我们把问题分解成可以分别考虑硬件和软件两个部分。在硬件上,CPU的计算性能和数据读写性能在这里是最重要的考虑方面。一般来讲CPU打节奏的频率越高,意味着运算速度越快,但这个问题更加复杂,不同设计的CPU可能会导致效率的完全不同。最典型的例子就是Intel的Pentium 4系列有比Pentium M更高的频率,但是1.6GHz的Pentium M就可以和2.4GHz的Pentium 4计算速度接近,这里面最重要的就是设计的改变,使得Pentium有更好的计算能力、更低的功耗。此外就是CPU的利用率,如果CPU大部分时间空置,再快的速度也没有用,这就需要CPU有很好的调度系统,能够将长时间的读写等待和快速的计算合理安排,使得CPU利用率提高。
数据的读写按照前文所述是一个分层系统,CPU首先从缓存读写,当缓存不能满足的时候会向内存读写,内存不能满足的时候会向硬盘读写。而实际上硬盘自己也带一块缓存,用来满足外部对硬盘的读写需求。如果CPU能够尽可能从缓存或者内存中读取数据,那么就没有必要从慢速的硬盘中读取数据了。由于读取数据的时候,通常可以猜测下一次读取的数据有很大可能在这个数据“附近”,内存和缓存可以通过预读取的方式把这部分数据读进来,所以读写速度不仅取决于这些存储设备的读写速度,还取决于缓存大小,以及预测到下一次数据的中奖率。对于传统的磁片硬盘来说,还要考虑磁针在盘片上滑动的速度,磁针寻找数据的范围,越靠近的磁针移动速度越快。
软件的效率需要考虑的就更多。把软件系统也按照计算机系统的方式进行分类,那么可以分成逻辑运算模块,数据读写模块,界面显示模块,这也是常见的软件编写的解决耦合的模式。对于逻辑运算模块来说,减少没必要的运算,提高采用的算法效率是能够大幅度提高程序速度的方法。好的算法可以让程序的复杂度从指数级的时间变成线性的时间。对于数据读写模块来说,尽量利用软件空闲的时候加载数据可以避免当数据使用时才读写导致的效率降低。对于界面现实模块来说,有时候可以利用动画或者中间步骤来掩饰逻辑运算或者数据读写的慢。软件对硬件的不同操作方式也会导致效率的不同,最典型的例子就是FastCopy等复制工具和Windows自带复制功能的比较,以及迅雷等下载工具和IE自带下载功能的比较。
这样分层、分模块地解构问题就完全解释清楚系统的效率问题了么?考虑这样一个问题,计算机A有一个单核3GHz 的CPU,计算机B有一个双核2GHz的CPU,其他所有配置一样;程序A和程序B都是从1到1亿验证这个数字是否是质数,不同的是程序A只使用一个CPU进行验证;程序B用一个CPU验证奇数,用一个CPU验证偶数。那么当程序A运行在计算机A上,程序B运行在计算机B上,哪个先结束呢?
一定会有人觉得答案是B先结束吧,因为B有两个核,相当于4GHz的计算速度,所以B的硬件更好;而B的程序至少和A是等价的,都是一一验证。但实际上,依然是A更快,因为程序B验证偶数的那部分根本没有工作,因为所有的偶数都不是素数,可以迅速判断,而大部分工作量都在验证奇数的部分,这部分所花的时间和A其实差不多,但是计算速度更慢,所以A能够更早完成。当然这个例子不够好,如果程序B能够更好的分配工作给CPU,那么B的确能够更快完成任务。这个例子是想说,即便计算机系统尽量的避免了硬件和软件之间的耦合,但针对不同的情况依然需要具体分析。