举例:一个网页同时给一百万个用户访问,网页文件存放在服务器的硬盘中,服务器的每次响应都需要从硬盘中读取这个网页,由于硬盘连接在南桥,读取速度和频率较慢,这会产生严重的服务器延迟(比如一个硬盘最高一次只能进行10万次的数据输出,那么剩下的九十万用户就得等着),这是非常搞糟的体验。因此,现在的服务器很多都采用了固态硬盘,并将硬盘直接连接在北桥上,以获取更高的读取性能。
6.主频和缓存主频可以理解为CPU的计算能力,主频越大,CPU在单位时间的计算能力越强。CPU的频率可以达到1GHZ,而内存的读取速度远远低于CPU的频率。给予木桶原理,即使CPU的速度再高,内存的读取效率跟不上,计算机的整体性能也难以提高。为此我们可以造更快的内存,但是这种方式造价极高。于是出现了缓存技术,缓存技术是在速度和造价之间的择中原则。
速度越快的部件,造价越高。因此最快的核心部分,我们只要一小块,然后在其外围放性能稍低(相对于核心)造价也稍低的设备,这就是缓存。CPU有一级缓存,二级缓存...缓存在CPU和内存之间起到了承上启下的作用。
缓存的工作,需要遵循程序的局部性原理,程序的局部性原理分为时间局部性和空间局部性。
时间局部性:刚刚访问的数据可能还会被访问,那么将该数据需要被缓存。
空间局部性:如果访问一个数据,那么离这个数据非常近的数据,也应该访问的比较快。因此在访问一个数据的时候,把其周围的数据也一并载入进来,这样就提高了其周围数据的访问速度。
程序的局部性原理,不仅应用在CPU的工作上,也用在码农的编码过程中,运用时间局部性和空间局部性,可以显著提高程序的运行效率。
举例:
Javascript中访问内层变量比访问全局变量快得多,因此我们在编码的过程中尽量少的依赖全局变量,可以提高运行的效率。(克制使用全局变量的好处不仅这一处,这里简单的举例说明)。
for循环中缓存变量,操作数据库的时候缓存字段等。
7.机器码,汇编,高级语言我们知道所有程序必须要编译机器码(二进制)才能被计算机识别和执行,我们也知道汇编是对机器码的抽象,让我们不用直面枯燥难懂的机器码,而使用易于人类的语言进行编程。汇编语言也叫作微码,是CPU厂商为我们暴露出来,通过微码我们可以进行针对CPU的编程。需要注意的是,不同的CPU架构不同,对于同一操作,其暴露出的微码也不尽相同。因此针对不同的CPU,我们需要分别对他们进行编程。尽管有些许蛋疼,但总比使用机器码编程好太多了。
高级语言是对汇编语言更高的抽象,结合一些额外的机制,来弥合CPU之间的不同。然后暴露出公共的API程序员调用,尽管对于这份API,其在不同的平台下可能会进行不同的实现,但是对于程序员,我们只需调用这个API,就可以实现平台的兼容,而我们自己再也不用考虑硬件的差异性了。
8.CPU的架构下面是一些常见的架构:
ARM:手持硬件设备(安卓,IOS)
x86:32位平台
x64:64位,来自AMD
安腾:来自惠普,Intel收购
Alpha:惠普
UltraSparc:SUN公司
Power:IBM
M68000:摩托罗拉(M68K)
PowerPC :IBM
9.CPU怎么执行一个程序单核的CPU,在某个时刻只能进行一次运算,为什么我们的程序看上去是并行执行呢?
这里需要引入切割机制,切割机制可以分为CPU切割和内存切割。
CPU切割:把CPU按照时间片(Slice)切割。比如一个Slice是5ms,那么每个程序只能运行5ms,下一个5ms就该换一个程序运行了(当然也可能仍然运行这个程序,具体取决于CPU的分配机制)。同时,CPU还应该有一个机制来记录程序的运行状态,以便程序在下一次运行的时候可以从先前的状态继续执行。
内存切割:引入分段机制,想象两个程序同时运行,而且都从内存的某一个编号开始占用(比如0x00000),那么后面的程序就会破坏掉前面程序的数据。现在引入了内存分段的机制,将内存分为一块块的区域,这些区域内部都从0x00000开始,那么程序就不会相互干扰了。
10.操作系统上例中,怎么保证每个程序在每个时间片中程序都是严格执行呢?如果程序赖着不走怎么办?