一、机械硬盘结构
机械硬盘大体上由以下几部分构成:
- 机械臂(磁头臂);
- 主轴;
- 多个成对的磁头和磁面。
在每个磁面上被分成多个磁道、多个扇面和多个扇区,它们的具体存在形式如下:
磁面上会有多个磁道,它们在一个磁面上拥有不同的磁道编号。
从磁面最外围离主轴最远的磁道到磁面最内侧离主轴最近的磁道,它们的编号从0开始,分别是0、1、2、3、4…….N(N大于等于10000,依据硬盘制作工艺不同而不同)。磁头将会顺着磁道基于磁面的转动读取数据,并且可以在各个磁道间切换位置。一个磁道被分为多个弧段,这些弧段称之为扇区。扇区是硬盘上存储数据的最基本物理单元。
所以,实际情况下,外部将要存储到硬盘上的数据不会一次性写满整个磁道,读取数据到外部时也不需要读取整个磁道的数据。注意,目前市场上无论哪个供应商提供的机械硬盘产品,每个物理扇区单元固定的存储容量都是512字节。只是根据硬盘密度不一样,单位磁面下的扇区数量也不一样。既然扇区是数据存储的基本单元,就意味着一次硬盘读写操作的最小数据量就是512字节。那么问题来了,是不是觉得512字节太小了点?是的,很多时候操作系统层面请求读写操作的文件都会大于一个扇区的单位容量。那么在物理层面上就需要两个甚至更多个扇区来存储这个文件,那么怎样来规划存储一个文件的若干扇区在磁面上的分布,从而达到减少读取时间的目的呢?
操作系统层面会将物理硬盘上两个或者多个能够连续读取的扇区组成合并成一个区域,称之为“簇”。
注意,这两个或者多个能够连续读取的扇区不一定在物理上是连续的。这是什么原因呢?这是因为硬盘转动的速度很快(标准速度为7200转/分),当磁头完成一个“扇区1”的读写后还来不及读取下一个连续的“扇区2”相邻的扇区就“飞”过去了,要等磁面再转动一圈到预定“扇区2”的位置才能继续进行读写。所以一个簇在物理磁面的分布可能是不连续的。实际上各个硬盘生产商都会设置一个“跳跃因子”来确定能够连续读取的扇区。如下图所示,四个不存在于连续物理位置的扇区构成一个簇。这样保证了磁面在旋转一圈的情况下就可以完成一个簇的全部读写。
最后说明一点,虽然扇面是硬件层面上机械磁盘读取数据的最小单元,但是“簇”才是操作系统层面上读取磁盘数据的最小单元。EXT文件系统和Btrfs文件系统,这两种文件系统定义的簇大小是不一样的。例如EXT文件系统的族大小可以有1KB(两个扇区)、2KB(四个扇区)、4KB(八个扇区)等多种选择。
那么如果一个文件太小,不需要用完一个簇怎么办呢?没办法,它有需要使用至少一个簇的硬盘空间。也就是说,在操作系统存储一个文件时,即使一个簇没有占满,剩下的簇空间也不能再使用了。这就是为什么一个文件在操作系统上有两个大小:一个是文件的实际大小、另一个是文件占用硬盘空间的大小。
二、机械硬盘性能瓶颈
1、影响机械硬盘性能的因素
当需要从硬盘上读取一个文件时,首先会要求磁头定位到这个文件的起始扇区。这个定位过程包括两个步骤:
- 磁头定位到对应的磁道;
- 主轴马达带动盘片转动到正确的位置。
这个过程所花费的时间被称为寻址时间。也就是说寻址时间实际上包含两部分:
- 磁头定位到磁道的时间为寻道时间;
- 等待盘片转动到正确位置的时间称为旋转等待时间。
硬盘寻址的目的是为了找到将要读取的文件的起始扇区,并开始去取数据。这就可以解释为什么硬盘上读取一个100MB大小的文件和读取1000个100KB大小的文件时间是完全不一样的现象了:
通常来说一个100MB的文件是存储在硬盘上可以连续读取的扇区上的,也就是说当硬盘需要读取这个文件时只需要进行一次寻址。
(为什么说是“通常”呢?因为前提是硬盘上至少要有一端连续空白的扇区,如果此时硬盘上碎片太多可能就找不到这样的连续空白区域了);而读取1000个文件时,由于这些文件的起始存储位不连续,所以每次都要进行寻址操作。
寻址时间是评价机械硬盘性能的重要指标,这个指标和硬盘转数、磁头数有直接关系:
硬盘转速越快的硬盘,在同样的寻址算法控制条件下将能够更快的将正确的扇区转动到磁头下方。
但是硬盘转速也不能做得无限快,因为硬盘转速越快要求的磁面工艺、主马达工艺也就越高,并且产生的噪音、温度也会成几何级增加。现在民用级、商用级和工业级硬盘上最常采用三种转速选择:5400转/分、7200转/分和10000转/分。磁头数,现在的机械硬盘中一般都包含了多个盘片并且分别使用独立的磁头。
这样做的主要作用是在硬盘密度不变的情况下增加机械硬盘的容量。实际上这样的做法也可以增加一定的硬盘性能,因为读取存储在不同磁面上的文件时,它们的寻道时间可以相对独立。但是其对性能的提示只能是有限的,因为这些盘片共享同一个主轴马达。
机械硬盘的工作原理导致了它的工作性能会远逊于内存,现在主流的7200转硬盘外部传输速度的理论峰值大概也就是200MB/s。那么问题又来了,天才的硬件工程师难道就没有办法增加机械硬盘读写性能了吗?
答案是否定的,硬件工程师为机械硬盘集成了缓存,并采用预读机制读取当前扇区的临近扇区。举个例子,当硬盘读取一个文件所在扇区时,会将这个扇区临近的若干扇区上的数据一同读取出来并存储到硬盘缓存中。这样做的原因是依据计算机科学中得一个著名原理:局部性原理。
局部性原理包括三层含义:
时间局部性;
如果一个信息项正在被访问,那么在近期它很可能被再次访问。空间局部性;
在近期将要被使用的信息很可能与现在正在使用的信息在空间地址上是临近的。顺序局部性。
在典型程序中,除转移类指令外,大部分指令是顺序进行的。局部性是所有高速缓存设计的基本原理依据。
局部性原理在硬盘硬件设备设计中被应用的依据是:当一个文件被读取时,在它临近扇区所存储的文件数据也将在近期被读取。所以硬盘会预先读取后者到缓存中,以便在不久的将来,这些数据被请求读取时直接从缓存中向外部设备输出文件数据。
局部性原理不止适合高速缓存这样的硬件设计,它也适用于软件设计:一个程序90%的时间运行在10%的代码上。
2、顺序读写和随机读写
上一小节已经提到硬盘的顺序读写和随机读写有非常大的性能差异,其中主要的原因是两者寻址操作上所耗费的时间存在巨大差异。那么顺序读写和随机读写的差异到底有多大呢?仅仅是靠上一小节的文字描述显然不能给读者数值化的认识,所以在本小节中我们将使用一款名叫CrystalDiskMark的测试软件,让读者具体体会一下两者的巨大区别:
以上是某品牌笔记本上5400转机械硬盘的测试截图,这个机械硬盘属于中低端硬盘,但是相同级别的硬盘在万元级以下的笔记本上却被大量使用,所以这个测试结果很能说明一些问题。首先解释一下以上截图中的几个主要项目:
在测试结果的上方写明了这是一个针对E盘符的测试,每一单项所测试的读写数据总量为500MB,并且每个单项测试分别执行5次。执行5次后综合每次的测试结果取平均值,最终形成这个单项的测试结果;
“Seq”和“Seq Q32T1”这两个选项分别代表没有IO队列的单线程顺序读写和一个深度为32的IO队列的单线程顺序读写,其中Q32代表队列深度为32,T1表示IO线程数为1。这个队列长度和IO线程数量都可以在CrystalDiskMark进行调整;
4K表示进行小文件读写测试时这些小文件的大小,这些4K文件将进行随机读和随机写测试。4K测试项是衡量固态硬盘性能的重要测试项,直接描述了固态硬盘的性能,这个我们将在下文进行说明。
从上图的测试结果来看,顺序读写的性能远远高于随机读写的性能,使用了IO队列的读性能又远远高于没有使用IO队列的读性能(且写性能基本持平)。当然以上的测试数值和选用的机械硬盘型号是密切相关的,但无论数值结果如何变化,最后都会符合以上所描述的性能规则。
例如如果您对7200转企业级硬盘进行测试,那么所有测试项的横向数值会高出很多;如果您的INTEL SSD 企业级固态硬盘卡进行测试,那么横向数值又会再高出很多倍。下图展示了INTEL SSD 750 企业级固态硬盘卡的测试结果(截图来源于网络):