一种基于固态盘读写特性的I/O调度方法与流程

文档序号:12462580阅读:443来源:国知局
一种基于固态盘读写特性的I/O调度方法与流程

本发明属于固态盘存储技术领域,更具体地,涉及一种基于固态盘不同读写特性的I/O调度方法。



背景技术:

固态盘(Solid state disk,简称SSD)是一种利用NAND闪存芯片作为数据永久存储的硬盘,随着NAND闪存芯片的生产成本下降,SSD的价格也越来越被人们所接受,SSD在数据中心、个人电脑、各种类型的移动设备上的使用越来越广泛。但是,由于长期以来构建存储系统的设备都是硬盘驱动器(Hard disk drive,简称HDD),现有的系统软件大多数是面向HDD进行设计和优化的,直接使用SSD替换掉HDD并不能最大限度地发挥SSD的高性能。因此,针对SSD进行系统软件优化具有十分重要的意义。

HDD是一种机械旋转式的硬盘,它的读写操作主要有以下几个步骤:

1、寻道:磁头传动装置将所有的磁头移动到待访问的柱面,并获取当前需要使用的磁头号;2、旋转等待:定位到相应的盘面和磁道后,盘面就会旋转,在旋转的过程中,磁头会读取其正下方的扇区中的扇区头标中的信息,与需要读取/写入的扇区号进行比对,如果不匹配则盘面会继续旋转,如果匹配则从此扇区开始读/写数据;3、完成数据读写。HDD读写操作很大一部分时间消耗在寻道和旋转等待上,而Linux内核中的IO调度算法所做的优化主要也是为了降低寻道和旋转等待的时间消耗。

在Linux系统中,现有的IO调度算法主要是Noop算法,CFQ算法Deadline算法和Anticipatory算法。其中CFQ、Deadline和Anticipatory算法针对HDD寻道时间长,采取了合并连续的读写请求,这样就可以在寻道 结束后进行连续的读写。Noop算法对读写请求不予合并,只将新的请求插入队尾。

然而,上述IO调度算法存在以下方面的问题:1、在SSD中,顺序的写和随机的写性能基本相同,所以对写请求进行合并并不能提高SSD的速率,反而会影响系统的性能;2、在SSD中,在不超过聚簇页大小的前提下合并读请求才会提高读效率,读请求大小超过聚簇页大小后并不会提高读效率。



技术实现要素:

针对现有技术的以上缺陷或改进需求,本发明提供了一种基于固态盘不同读写特性的I/O调度方法,其目的在于,解决现有IO调度方法中存在的连续读请求合并后过大或不能被合并、以及写请求存在不必要的合并的技术问题。

为实现上述目的,按照本发明的一个方面,提供了一种基于固态盘读写特性的IO调度方法,包括以下步骤:

(1)接收来自上层应用并经过文件系统处理后的bio请求,并判断该bio请求的类型是读请求还是写请求,如果是读请求则转入步骤(2),如果是写请求则转入步骤(3);

(2)判断该读请求是否能够与其邻近的读请求进行合并,若不能合并,则直接转入步骤(4);若可以合并且合并后的大小不超过聚簇页的大小,则将其与邻近的读请求进行合并,合并后的读请求仍然可以与其邻近的读请求进行合并,并且应当确保合并后的大小不超过聚簇页的大小。将最终合并后的读请求放入读队列和读红黑树中,以供系统读取数据。然后转入步骤(4)。

(3)判断该写请求是否能够与缓存中的写请求进行合并,如果可以则进行合并,并将合并后的写请求插入调度器队列末端,并转入步骤(4);否则判断其能否与哈希表中的写请求进行合并,如果可以则进行合并,并 将将合并后的写请求插入调度器队列末端,并转入步骤(4);

(4)将调度器队列中的请求分发到设备驱动器的请求队列中。

优选地,步骤(2)包括以下子步骤:

(2.1)针对该读请求,判断是否存在上次合并的读请求,若存在,则跳转到步骤(2.2);否则跳转到步骤(2.3);

(2.2)判断该读请求与上次合并后的读请求能否进行合并。如果不能合并,则跳转到步骤(2.3),如果能前向合并,则跳转到步骤(2.4),如果能后向合并,则跳转到步骤(2.5);

(2.3)判断该读请求能否与哈希链表中的请求进行后向合并,如果能则跳转到步骤(2.5);否则跳转到步骤(2.6);

(2.4)完成可前向合并的读请求Rfrq与该读请求的合并,并判断前向合并之后的读请求Rfrq能否继续与调度器中读红黑树中按照请求的起始访问地址排序的Rfrq的前一个读请求Rprev继续进行前向合并。能则跳转到步骤(2.7),否则跳转到步骤(2.8);

(2.5)完成可后向合并的请求Rbrq与该读请求的合并,并判断后向合并之后的请求Rbrq能否继续与调度器中读红黑树中按照请求的起始访问地址排序的Rbrq的后一个请求Rnext继续进行后向合并。能则跳转到步骤(2.9),否则跳转到步骤(2.10);

(2.6)判断该读请求能否与调度器中读红黑树中的请求进行前向合并,如果能则跳转到步骤(2.4),否则跳转到步骤(2.11);

(2.7)完成读请求Rfrq与读请求Rperv的前向合并,删除调度器读队列、读红黑树以及通用块层哈希链表中的Rfrq请求;同时根据被合并的读请求的大小改变Rprev在哈希链表中的位置;并将合并后的最晚服务时间设置为Rfrq和Rprev的最晚服务时间中较小的一个;最后将上次合并的读请求标记为Rfrq。

(2.8)将上次合并的读请求设置为Rfrq,并在读红黑树中更新Rfrq的 起始地址;

(2.9)完成请求Rbrq与请求Rnext的后向合并,在调度器的读队列、读红黑树以及通用块层的哈希链表中删除Rnext请求,更新Rbrq请求在哈希链表中的位置,将Rbrq和Rnext中较早的服务时间设置为合并后的读请求的服务时间,将Rbrq标记为上次合并的读请求,并跳转到步骤(2.14);

(2.10)将Rbrq标记为上次合并的读请求,并更新Rbrq请求在哈希链表中的位置,结束转换;

(2.11)为该bio请求分配一个请求Rnrq,并用该bio请求初始化Rnrq,并判断Rnrq是否具有合并属性,如果有则跳转到步骤(2.12);否则跳转到步骤(2.13);

(2.12)将Rnrq请求加入哈希链表,并判断是否存在上次合并的读请求。如果存在,则直接跳转到步骤(2.13);否则先将Rnrq标记为上次合并的读请求,并跳转到步骤(2.13);

(2.13)将Rnrq请求加入调度器中读队列末尾以及读红黑树中。

优选地,步骤(3)包括以下子步骤:

(3.1)针对该写请求,判断是否存在上次合并的写请求,如果存在,跳转到步骤(3.2);否则跳转到步骤(3.3);

(3.2)判断该bio请求是否能够与上次合并的写请求进行合并,如果能够前向合并,跳转到步骤(3.4);如果能够进行后向合并,跳转到步骤(3.5);如果不能合并跳转到步骤(3.3);

(3.3)判断该bio请求能否与哈希链表中的请求进行后向合并,如果能则跳转到步骤(3.5);否则跳转到步骤(3.6);

(3.4)将该bio请求与上次合并的写请求进行前向合并,并判断合并之后还能否继续与调度器中写链表中其前一个请求Wprev继续进行合并。如果能与Wprev合并,则跳转到步骤(3.7),否则跳转到步骤(3.8);

(3.5)完成bio请求与可后向合并的请求Wbrq的后向合并,并判断合并 之后的Wbrq能否与调度器写链表中Wbrq的下一个请求Wnext继续进行合并。能则跳转到步骤(3.9);否则跳转到步骤(3.10);

(3.6)为该bio请求分配一个新请求Wnrq,并用该bio请求初始化Wnrq。然后判断Wnrq是否具有合并属性。有则跳转到步骤(3.11);否则跳转到步骤(3.12);

(3.7)完成Wfrq与Wprev的合并,并在调度器的写链表、哈希链表中删除Wfrq,接着需要调整Wprev在哈希链表中的位置,最后将Wprev标记为上一次合并的写请求,已经将该bio请求转化为了写请求,结束本次转换;

(3.8)将Wfrq标记为上次合并的写请求,已经将该bio请求转化为了写请求,结束本次转换;

(3.9)完成Wbrq与Wnext的合并,并在调度器的写链表、哈希链表删除Wnext,接着需要调整Wbrq在哈希链表中的位置,最后将Wbrq标记为上次合并的写请求,已经将该bio请求转化为了写请求,结束本次转换;

(3.10)调整Wbrq在哈希链表中的位置,并将Wbrq标记为上次合并的写请求,已经将该bio请求转化为了写请求,结束本次转换;

(3.11)将Wnrq加入哈希链表中,并判断上次合并的写请求是否存在。若不存在,则将Wnrq标记为上次合并的写请求,并跳转到步骤(3.12);否则,直接跳到步骤(3.12);

(3.12)将Wnrq加入调度器写链表的尾部,从而将该bio请求转化为了写请求。

优选地,步骤(4)包括以下子步骤:

(4.1)判断调度器队列中目前分发请求所处的阶段是处于读批处理阶段还是写批处理阶段,如果处于读批处理阶段,则跳转到步骤(4.2);如果处于写批处理阶段,则跳转到步骤(4.3),

(4.2)判断读批处理阶段分发的请求总数是否已超过阈值。若已超过阈值,则跳转到步骤(4.4),否则跳转到步骤(4.5);

(4.3)判断写批处理阶段分发的请求总数是否已达上限,若已达上限,跳转到步骤(4.4),否则跳转到步骤(4.6);

(4.4)创建一个批处理阶段,并确定调度器队列中是否存在对应的读请求吗,若存在,跳转到步骤(4.9);否则跳转到步骤(4.10);

(4.5)将调度器中待分发的请求Drq设置为next_rq[read],并跳转到步骤(4.7);

(4.6)将调度器中待分发的请求Drq设置为next_rq[write],并跳转到步骤(4.8);

(4.7)将Drq分发到设备驱动层的请求队列中,从调度器的读链表和读红黑树中删除该Drq,并将next_rq[read]设置为Drq在调度器的读红黑树中的下一个请求,最后对该操作进行计数,结束本次请求分发过程;

(4.8)将Drq分发到设备驱动层的请求队列中,从调度器的写链表中删除Drq,设置next_rq[write]为Drq在调度器写链表中的下一个请求,最后对该操作进行计数,结束本次请求分发过程;

(4.9)判断调度器的写链表中是否存在请求,如果不存在,则跳转到步骤(4.11);如果存在,则继续判断是否存在超时的写请求或者写请求被饥饿的次数已达上限,如果判定结果为真,则跳转到步骤(4.12);否则跳转到步骤(4.11);

(4.10)判断调度器的写链表中是否存在请求,若存在,则跳转到步骤(4.12);否则调度器中不存在待分发的请求,结束本次请求分发过程;

(4.11)判断next_rq[read]是否存在。若存在,跳转到步骤(4.13);否则跳转到步骤(4.14);

(4.12)将写请求被饥饿的次数置0。然后判断是否存在超时的写请求或者next_rq[write]是否为空。如果判定结果为真,跳转到步骤(4.15);否者跳转到步骤(4.16);

(4.13)将待分发请求Drq设置为next_rq[read],设置batching=0,开始 创建一个读批处理阶段,跳转到步骤(4.7);

(4.14)将待分发请求Drq设置为调度器读链表中的第一个请求,设置batching=0,开始创建一个读批处理阶段,跳转到步骤(4.7);

(4.15)将待分发请求Drq设置为调度器写链表中的第一个请求,设置batching=0,开始创建一个写批处理阶段,跳转到步骤(4.8);

(4.16)将待分发请求Drq设置为next_rq[write],设置batching=0,开始创建一个写批处理阶段,跳转到步骤(4.8)。

总体而言,通过本发明所构思的以上技术方案与现有技术相比,能够取得下列有益效果:

(1)本发明能够解决现有方法中存在的连续的读请求合并后过大或不合并的问题:由于采用了步骤(2.2)步骤(2.4)步骤(2.5)和步骤(2.7),因此可以解决现有Noop算法中对读请求不合并,以及CFQ、Deadline、Anticipatory算法中对读请求合并过大的问题。

(2)本发明能够解决现有方法中存在的对连续的写请求不必要的合并的问题:由于采用了步骤(3.4)步骤(3.5)步骤(3.7)和步骤(3.9),因此可以解决现有IO调度算法中对连续的写请求进行合并的问题。

(3)本发明充分利用固态盘在不同访问模式下读写性能:考虑到SSD中顺序模式下读请求的性能远远高于随机模式下读请求的性能,对读请求不仅按照请求到来的时间在链表中排队,还按照读请求的起始访问地址在红黑树中排序,以构造读请求的顺序性,对排序之后的读请求进行前向合并和后向合并;考虑到顺序模式下写请求的性能和随机模式下写请求的性能基本相同,写请求只需要按照请求到来的时间在链表中排队,不需要在红黑树中排序构造写请求的顺序性,对写请求也只进行后向合并。

(4)本发明充分利用固态盘丰富的并行性:合并读写请求时,考虑到SSD中最小的读写操作单元是页,而为了利用SSD内部的并行性,读写操作有可能是以聚簇页为最小操作单元,通过黑盒测试的方式获取聚簇页的 大小,并合并请求时,保证合并之后的请求不超过聚簇页的大小。当请求大小达到聚簇页大小时,继续合并请求,不会带来性能的提升,反而会造成SSD设备空闲等待,降低性能。

附图说明

图1是Linux操作系统固态盘访问的I/O路径。

图2是本发明基于固态盘不同读写特性的I/O调度方法的流程图。

图3是本调度方法中读bio请求到请求的转变。

图4是本调度方法中写bio请求到请求的转变。

图5是本调度方法中分发请求到设备驱动层。

具体实施方式

为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本发明进行进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。此外,下面所描述的本发明各个实施方式中所涉及到的技术特征只要彼此之间未构成冲突就可以相互组合。

如图1所示,上层应用通过系统调用读写模块发起的IO请求,首先会经过虚拟文件系统层(Virtual file system,简称VFS),并到达真实需要访问的文件系统层,接着会经过通用块层和IO调度层,最后达到SCSI设备驱动层,才能向底层磁盘请求数据。本发明基于固态盘不同读写特性的I/O调度方法工作在I/O调度层。具体完成如下两个功能:

1、配合通用块层将文件系统层下发的bio请求按照一定的策略封装成请求,并加入调度层的请求队列;

2、将IO调度层请求队列中的请求按照一定的策略分发到下层的SCSI设备驱动层的请求队列中。使得到达固态盘的读请求呈现更强的顺序性,能够合理适度地利用固态盘内部的并行性以及避免读写请求之间的相互干扰,从而能够提高整个固态盘系统的I/O性能。

本发明的整体思路在于,其充分考虑了固态盘中读写请求的相互干扰,将读写请求分离,批量处理读请求和写请求;考虑到顺序模式下读请求的性能远远高于随机模式下读请求的性能,对读请求不仅按照请求到来的时间在链表中排队,还按照读请求的起始访问地址在红黑树中排序,以构造读请求的顺序性,对排序之后的读请求进行前向合并和后向合并;考虑到顺序模式下写请求的性能和随机模式下写请求的性能基本相同,写请求只需要按照请求到来的时间在链表中排队,不需要在红黑树中排序构造写请求的顺序性,对写请求也只进行后向合并;考虑到固态盘中存在着可利用的最优并行度,当合并请求达到聚簇页大小时,不继续进行合并,请求达到聚簇页大小时已经可以充分利用固态盘中丰富的并行性,继续合并请求,不会带来性能提升,反而会造成SSD设备空闲等待,降低性能。

本发明在Linux内核的I/O调度层实现,具体完成如下两个功能:1、配合通用块层将文件系统层下发的bio请求按照一定的策略封装成请求,并加入调度层的请求队列;2、将IO调度层请求队列中的请求按照一定的策略分发到下层的SCSI设备驱动层的请求队列中。使得到达固态盘的读请求呈现更强的顺序性,能够合理适度地利用固态盘内部的并行性以及避免读写请求之间的相互干扰,从而能够提高整个固态盘系统的I/O性能。

如图2所示,本发明基于固态盘读写特性的IO调度方法包括以下步骤:

(1)接收来自上层应用并经过文件系统(在本实施方式中,该文件系统是ext4文件系统)处理后的bio请求,并判断该bio请求的类型是读请求还是写请求,如果是读请求则转入步骤(2),如果是写请求则转入步骤(3);

(2)判断该读请求是否能够与其邻近的读请求进行合并,若不能合并,则直接转入步骤(4);若可以合并且合并后的大小不超过聚簇页的大小,则将其与邻近的读请求进行合并,合并后的读请求仍然可以与其邻近的读请求进行合并,并且应当确保合并后的大小不超过聚簇页的大小。将最终合并后的读请求放入读队列和读红黑树中,以供系统读取数据。然后转入 步骤(4)。

(3)判断该写请求是否能够与缓存中的写请求进行合并,如果可以则进行合并,并将合并后的写请求插入调度器队列末端,并转入步骤(4);否则判断其能否与哈希表中的写请求进行合并,如果可以则进行合并,并将将合并后的写请求插入调度器队列末端,并转入步骤(4);

(4)将调度器队列中的请求分发到设备驱动器的请求队列中,过程结束。

如图3所示,本发明方法中的步骤(2)包括以下子步骤:

(2.1)针对该读请求,判断是否存在上次合并的读请求,若存在,则跳转到步骤(2.2);否则跳转到步骤(2.3);

(2.2)判断该读请求与上次合并后的读请求能否进行合并。如果不能合并,则跳转到步骤(2.3),如果能前向合并,则跳转到步骤(2.4),如果能后向合并,则跳转到步骤(2.5);具体而言,如果该读请求与前一读请求在地址上是连续的,而且合并后的请求大小不超过聚簇页大小,则表示能够前向合并,如果该读请求的地址与后一读请求在地址上是连续的,且合并后的读请求大小不超过聚簇页大小,则表示能够后向合并;

本步骤的优点在于:通过缓存上一次合并的请求,在几乎不增加开销的情况下可以大大缩短搜寻能与当前读请求合并的请求的时延,提高合并请求的效率,增加性能;另外合并之后请求的大小不超过聚簇页大小,可以充分利用SSD内部丰富的并行性,又不至于过度合并造成SSD设备空闲等待,可以进一步提高性能;

(2.3)判断该读请求能否与哈希链表中的请求进行后向合并,如果能则跳转到步骤(2.5);否则跳转到步骤(2.6);

(2.4)完成可前向合并的读请求Rfrq与该读请求的合并,并判断前向合并之后的读请求Rfrq能否继续与调度器中读红黑树中按照请求的起始访问地址排序的Rfrq的前一个读请求Rprev继续进行前向合并。能则跳转到步 骤(2.7);否则跳转到步骤(2.8);

(2.5)完成可后向合并的请求Rbrq与该读请求的合并,并判断后向合并之后的请求Rbrq能否继续与调度器中读红黑树中按照请求的起始访问地址排序的Rbrq的后一个请求Rnext继续进行后向合并。能则跳转到步骤(2.9),否则跳转到步骤(2.10);

(2.6)判断该读请求能否与调度器中读红黑树中的请求进行前向合并,如果能则跳转到步骤(2.4),否则跳转到步骤(2.11);

(2.7)完成读请求Rfrq与读请求Rperv的前向合并,删除调度器读队列、读红黑树以及通用块层哈希链表中的Rfrq请求;同时根据被合并的读请求的大小改变Rprev在哈希链表中的位置;并将合并后的最晚服务时间设置为Rfrq和Rprev的最晚服务时间中较小的一个;最后将上次合并的读请求标记为Rfrq,本次转换结束。具体而言,以上步骤就是删除被合并后读请求的副本,以及调整合并后的读请求的服务时间和在哈希链表中的位置,并记录上次合并的读请求的地址;

本步骤的优点在于:通过前向合并,可以将小请求聚合成大请求,可以大大提高系统的吞吐量;

(2.8)将上次合并的读请求设置为Rfrq,并在读红黑树中更新Rfrq的起始地址;

(2.9)完成请求Rbrq与请求Rnext的后向合并,在调度器的读队列、读红黑树以及通用块层的哈希链表中删除Rnext请求,更新Rbrq请求在哈希链表中的位置,将Rbrq和Rnext中较早的服务时间设置为合并后的读请求的服务时间,将Rbrq标记为上次合并的读请求,并跳转到步骤(2.14);

本步骤的优点在于:通过后向合并,可以将小请求聚合成大请求,可以大大提高系统的吞吐量;

(2.10)将Rbrq标记为上次合并的读请求,并更新Rbrq请求在哈希链表中的位置;结束转换;

(2.11)为该bio请求分配一个请求Rnrq,并用该bio请求初始化Rnrq,并判断Rnrq是否具有合并属性,如果有则跳转到步骤(2.12);否则跳转到步骤(2.13);

(2.12)将Rnrq请求加入哈希链表,并判断是否存在上次合并的读请求。如果存在,则直接跳转到步骤(2.13);否则先将Rnrq标记为上次合并的读请求,并跳转到步骤(2.13);

(2.13)将Rnrq请求加入调度器中读队列末尾以及读红黑树中;

本步骤的优点在于:设置读请求的最晚需要被服务时间,优先服务超时的读请求,避免某一读请求长期得不到服务;另外对读请求不仅按照请求到来的时间在链表中排队,还按照读请求的起始访问地址在红黑树中排序,以构造读请求的顺序性,以充分利用顺序模式下远远优于随机模式下的读性能;

如图4所示,本发明方法中的步骤(3)包括以下子步骤:

(3.1)针对该写请求,判断是否存在上次合并的写请求,如果存在,跳转到步骤(3.2);否则跳转到步骤(3.3);

(3.2)判断该bio请求是否能够与上次合并的写请求进行合并,如果能够前向合并,跳转到步骤(3.4);如果能够进行后向合并,跳转到步骤(3.5);如果不能合并跳转到步骤(3.3);

本步骤的优点在于:通过缓存上一次合并的请求,在几乎不增加开销的情况下可以大大缩短搜寻能与当前bio请求合并的请求的时延,提高合并请求的效率,增加性能;另外合并之后请求的大小不超过聚簇页大小,可以充分利用SSD内部丰富的并行性,又不至于过度合并造成SSD设备空闲等待,可以进一步提高性能;

(3.3)判断该bio请求能否与哈希链表中的请求进行后向合并,如果能则跳转到步骤(3.5);否则跳转到步骤(3.6);

(3.4)将该bio请求与上次合并的写请求进行前向合并,并判断合并之 后还能否继续与调度器中写链表中其前一个请求Wprev继续进行合并。如果能与Wprev合并,则跳转到步骤(3.7),否则跳转到步骤(3.8);

(3.5)完成bio请求与可后向合并的请求Wbrq的后向合并,并判断合并之后的Wbrq能否与调度器写链表中Wbrq的下一个请求Wnext继续进行合并。能则跳转到步骤(3.9);否则跳转到步骤(3.10);

本步骤的优点在于:通过后向合并,可以将小请求聚合成大请求,可以大大提高系统的吞吐量;

(3.6)为该bio请求分配一个新请求Wnrq,并用该bio请求初始化Wnrq。然后判断Wnrq是否具有合并属性。有则跳转到步骤(3.11);否则跳转到步骤(3.12);

(3.7)完成Wfrq与Wprev的合并,并在调度器的写链表、哈希链表中删除Wfrq,接着需要调整Wprev在哈希链表中的位置,最后将Wprev标记为上一次合并的写请求,已经将该bio请求转化为了写请求,结束本次转换;

(3.8)将Wfrq标记为上次合并的写请求,已经将该bio请求转化为了写请求,结束本次转换;

(3.9)完成Wbrq与Wnext的合并,并在调度器的写链表、哈希链表删除Wnext,接着需要调整Wbrq在哈希链表中的位置,最后将Wbrq标记为上次合并的写请求,已经将该bio请求转化为了写请求,结束本次转换;

(3.10)调整Wbrq在哈希链表中的位置,并将Wbrq标记为上次合并的写请求,已经将该bio请求转化为了写请求,结束本次转换;

(3.11)将Wnrq加入哈希链表中,并判断上次合并的写请求是否存在。若不存在,则将Wnrq标记为上次合并的写请求,并跳转到步骤(3.12);否则,直接跳到步骤(3.12);

(3.12)将Wnrq加入调度器写链表的尾部,从而将该bio请求转化为了写请求;

本步骤的优点在于:充分考虑到SSD中顺序写请求的性能与随机写请求 的性能基本相同,对写请求只按照到来时间在链表中排队,不需要按照写请求的起始访问地址在红黑树中排序,构造写请求的顺序性,消除了排序的性能花销,提高了性能;

如图5所示,本发明方法中的步骤(4)包括以下子步骤:

(4.1)判断调度器队列中目前分发请求所处的阶段是处于读批处理阶段还是写批处理阶段。如果处于读批处理阶段,则跳转到步骤(4.2);如果处于写批处理阶段,则跳转到步骤(4.3);具体而言,就是通过获取程序运行时next_rq[dir]变量的值来判断分发请求是处于读批处理阶段还是写批处理阶段。本步骤的优点在于:批量分发读请求或写请求,避免SSD中读写请求之间的相互干扰造成的性能下降;

(4.2)判断读批处理阶段分发的请求总数是否已超过阈值。若已超过阈值,则跳转到步骤(4.4),否则跳转到步骤(4.5);在本发明中,该阈值的取值范围是(0,16]。

(4.3)判断写批处理阶段分发的请求总数是否已达上限,若已达上限,跳转到步骤(4.4);否则跳转到步骤(4.6);

(4.4)创建一个批处理阶段,并确定调度器队列中是否存在对应的读请求吗,若存在,跳转到步骤(4.9);否则跳转到步骤(4.10);

(4.5)将调度器中待分发的请求Drq设置为next_rq[read],并跳转到步骤(4.7);

(4.6)将调度器中待分发的请求Drq设置为next_rq[write],并跳转到步骤(4.8);

(4.7)将Drq分发到设备驱动层的请求队列中,从调度器的读链表和读红黑树中删除该Drq,并将next_rq[read]设置为Drq在调度器的读红黑树中的下一个请求,最后对该操作进行计数,结束本次请求分发过程;

本步骤的优点在于:批量分发读请求阶段,从红黑树种获取下一个读请求,以利用红黑树的排序功能,构造读请求的顺序性,充分利用SSD中顺 序读的性能远远高于随机读的性能;

(4.8)将Drq分发到设备驱动层的请求队列中,从调度器的写链表中删除Drq,设置next_rq[write]为Drq在调度器写链表中的下一个请求,最后对该操作进行计数,结束本次请求分发过程;

本步骤的优点在于:批量分发写请求阶段,从链表中获取下一个写请求,不需要构造写请求的顺序性,从而省去了排序的开销,充分利用SSD中随机写的性能基本与顺序写的性能相同;

(4.9)判断调度器的写链表中是否存在请求,如果不存在,则跳转到步骤(4.11);如果存在,则继续判断是否存在超时的写请求或者写请求被饥饿的次数已达上限。如果判定结果为真,则跳转到步骤(4.12);否则跳转到步骤(4.11);

本步骤的优点在于:优先创建读请求的批量分发过程,赋予读请求较高的优先级,已满足用户对读请求响应时间要求比较严格的需求,另外为了防止写请求被饿死,也设置了写请求最晚需要被服务的时间,当有写请求超时时,优先分发超时的写请求;

(4.10)判断调度器的写链表中是否存在请求。若存在,则跳转到步骤(4.12);否则调度器中不存在待分发的请求,结束本次请求分发过程;

(4.11)判断next_rq[read]是否存在。若存在,跳转到步骤(4.13);否则跳转到步骤(4.14);

(4.12)准备进行写请求的批量处理阶段,将写请求被饥饿的次数置0。然后判断是否存在超时的写请求或者next_rq[write]是否为空。如果判定结果为真,跳转到步骤(4.15);否者跳转到步骤(4.16);

(4.13)将待分发请求Drq设置为next_rq[read],设置batching=0,开始创建一个读批处理阶段,跳转到步骤(4.7);

(4.14)将待分发请求Drq设置为调度器读链表中的第一个请求,设置batching=0,开始创建一个读批处理阶段,跳转到步骤(4.7);

(4.15)将待分发请求Drq设置为调度器写链表中的第一个请求,设置batching=0,开始创建一个写批处理阶段,跳转到步骤(4.8);

(4.16)将待分发请求Drq设置为next_rq[write],设置batching=0,开始创建一个写批处理阶段,跳转到步骤(4.8)。

本领域的技术人员容易理解,以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1