如果像SSD一样,随机读写还是比连续读写慢,那么页式虚拟内存管理这层转换是不是会浪费很大的性能?而且即使没有页式内存管理,在BIOS层面上的「物理地址」跟真正的内存条上的存储单元位置就已经不是连续对应的了,是不是也会浪费性能呢?

如果是一样的,那么为什么同样是晶体管制成的Flash晶元(SSD)的随机吞吐量就远小于连续读写?如果说机械硬碟随机访问慢是因为需要寻道,SSD是没有寻道时间的啊,访问任意一个块需要的时间应该都是一样的吧?


谢邀。DRAM随机读写是比连续读写要慢,我们来看实际的数据:

AMD和Intel的差距不在本文范围内,我们暂且忽略。我们专注看第一条,就会发现:

按位元组纯随机读取延迟 &> 在一个page里面随机读取延迟 &> 顺序连续读取延迟

这是为什么呢?我们分别来看看:

随机读取延迟为什么高?

不是说好内存是随机读取设备吗?为什么随机读取延迟还会高呢?这里有两个原因:Burst读取Prefetcher

我们知道内存条是有64个Bit的数据线:DQ0-DQ63,共8个位元组。如果读取某个地方的数据,需要不少步骤(大致):

  1. Precharge。

2. 行有效。RAS#低电平,CAS#高电平。意味著现在行地址有效,同时在A0-A13传送地址信号,即2^13个Row可以选择。

3. 列有效。RAS#高电平,CAS#低电平。意味著列地址有效,这时在A0-A13上传送的是列地址。没错,A0-A13是行列共用的,所以每个格子选择需要有1和2两步才能唯一确定。

4. 数据读出或写入。根据COMMAND进行读取或者写入。在选定好小方格后,就已经确定了具体的存储单元,剩下的事情就是数据通过数据I/O通道(DQ)输出到内存汇流排上了。

而我们Cache line是64个位元组,那么每次刷新Cache line是不是要来8次这么多步骤呢?并不是,有Burst读取,我们没用的多余的Prechange,行列选择也只要一次,就可以连续读取8个8位元组数据了,也就是Burst Length(BL)是8。如果我们读了一半,不需要这么多,可以用Burst Chop来省电。这样我们就省了7个CL、tRCD、tRP延迟,总延迟能不下降吗?

Burst mode十分普遍,几乎出现在所有需要传输数据的地方,大到网路传输,小到UPI等等通信,DRAM和SSD都有Burst传输。

那么是不是我不是一个位元组一个位元组读,而是8个位元组8个位元组读,随机和顺序就完全一样呢?也不是,CPU中为了提高性能,有很多预取器(Prefetcher)。Prefetcher种类众多,有指令的,有数据的,有些Prefetcher对某种work load有用,有些则在某种work load中有反作用。Prefetcher也会让我们顺序读取比随机读取更快,它省了指令流水线的部分时间(想想为什么)。

为什么跨page最慢呢?

最后分析一下跨Page随机比同page随机慢的原因。跨Page有可能要刷TLB,如果不停切page,则必然大量刷新TLB。TLB刷新会消耗大量的Cycle,这是它最慢的原因。


内存每一个bank只有一个buffer,读写都要通过这个buffer来进行,这个buffer只能装载内存的一行,也叫page。

存在buffer中的行的状态称为page opened,而同一bank其他行的状态称为page closed。

如果到来的命令正好是访问当前open状态的行,那么这叫page hit,只需要一个cas命令(列选择,既读或者写)即可完成操作。

如果所有行处于close状态,这叫page miss,需要先发一个ras命令,也叫active命令,行选择。然后再发cas命令完成操作。

如果当前访问的行和open状态的行不是同一行,那么这叫page conflict。需要先发一个pre-charge命令,关闭当前open的行,然后再ras命令,最后cas命令完成操作。

所以memory controller主要使用两种page策略,open page 和close page。open page,顾明思议,读写后不会立刻进行pre-charge,这种策略对连续地址读写方式更友好,但一旦出现page conflict,受到的影响就很明显。而close page则是每次读写后立刻pre-charge,这样每次到来的命令都是page miss,不会出现page conflict,对随机读写更加友好。

一般来说,连续命令以连续地址操作较多,所以一般性能好优化好的memory controller采用open page方式的占多数,需要对命令进行重排序,再调度,保持同一地址的读写顺序,pre-charge预测等等优化,还要采取对应的地址映射方式(这块挺复杂,简单的说,可以把collum地址映射到地址的低位,采用CS interleave,把bank group和bank地址映射到低位,bank group比bank更低为好),目的是增加page hit,减少page conflict。

close page方式是结构相对简单的memory controller主要采用。所以连续地址读写和随机地址读写的速度,根据memory controller采用的page策略有关,当然大部分是连续地址读写速度更快带宽更高。

另外,从读命令到写命令所用切换时间比从写到读少,这是因为数据操作其实主要在buffer中进行,如果前一个是读,读命令不会影响数据,buffer中数据始终和open的行中数据保持一致,所以pre-charge的时候不需要把buffer中数据写回行中。而写命令会改变数据,需要一个写回的过程。所以还尽量要减少写到读的切换,在保证正确读写顺序的基础上。


先说结论吧:DRAM的随机读写速度必然慢于连续读写。

主要原因是CPU存在著多层次的cache,随机读写会造成大量的cache miss,必然引发速度下降。除非是完全没有cache的CPU,比如Intel第一代的8086 CPU。

因为不存在cache,所以随机读写速度基本上跟连续读写是一样的,但8086的随机跳转性能会差一些,因为8086上还是有几个位元组的指令预取缓存的。

回到题主的问题,段页式转化是必然要产生性能损失的,极端的例子是虚拟化,虚拟化是两次翻译,先从虚拟机的虚地址转换成虚拟机的物理地址,再转换成实际物理地址,所以虚拟机的内存访问性能要慢于非虚拟机,但这个浪费并不是「很大」,Intel号称虚拟机的内存访问性能比非虚拟化模式慢10%~30%左右,这是过去的数据,不知道现在什么样了,所以算不上「浪费很大」。

实际CPU在翻译段页地址的时候,页面内的地址翻译是有缓存的,比如对于指令来说,只要不踩到页边界,是不会触发新的地址翻译(这里特别说明一下:操作系统从实模式切换到保护模式的时候,也用了这种技巧:不跨页,不触发地址翻译)。而跨页的话,也并非到RAM里拿页表,那样开销太大了,有TLB的存在可以提高地址翻译速度。

BIOS层面上的物理地址到实际物理设备的地址翻译是在内存控制器里做的,这方面可以认为是没有性能损耗的,因为翻译的过程是可以认为是静态的,就算是有开销,也远远低于虚地址的翻译——这个是动态的,因为页表是可调整的。

不管地址翻译的开销有多大,也比不上cache miss,这个会严重影响性能。

有一些特殊的应用场合,会为了保证性能或者实时性,会关掉页表,或者做大页一一映射,这就是为了尽量让地址翻译的影响降到最低。

-------------------------------

再说SSD的问题,SSD是不需要寻道,但SSD也是有cache的,SSD内部有一张表,保存著逻辑扇区到物理扇区的映射,为了保证性能,这个映射表运行时是被SSD放到主控的cache里的,但基于成本的考虑不会是全cache的,那么这里就会有cache miss的可能,cache miss的开销可能是微秒甚至毫秒级,这样延迟就很大了。

随机写就更复杂一点,除了SSD本身的cache miss之外,SSD写操作的最小单元要大于读,SSD读的最小单位一般是一个扇区(512B/4K),擦除的最小单位是一个block,可能是128KB甚至更大,擦除一个block的开销是毫秒级的延迟,如果连续写128KB,可能是只需要擦除一个block,但如果是随机写,那可能是擦除非常多的block,其开销是完全不一样的。

所以即使SSD不需要寻道,其随机读写的性能也慢于连续读写。


真正的随机存储贵啊,

cpu的论个算的寄存器就是,论kb算的l1缓存也算是吧(虽然也是以行为单位,但粒度比内存里要小多了),要实现同容量所需晶体管比内存那串列的结构得多出个量级,而且非常难放大规模(就像道路密度大就住宅少会放大交通需求一样,超大城市不分区你规划99%道路一样会堵死),

ssd存储粒度比内存更大,同容量比内存所需晶体管少的多还不需要那么高频.,所以速度会慢更多.


连续和随机读写速度不一样,同样是随机读写比连续读写慢不少。

虚拟内存的策略是时间换空间,本身的意义就是牺牲性能换空间,可以让程序装进去运行而不是不够用。

地址转换是为了方便地址管理吧,不然大家都用物理地址管理起来乱糟糟的。。

你这个追求绝对性能的思路很激进啊


ram既然叫随机存储器,顾名思义读取时间与信息的位置无关。

ssd使用的nand flash以页为单位读取数据,每次至少读写一个page。这样连续读写速度肯定高于需要每次进行定址的随机读写速度。

内存分页的确会降低随机速度。但是如果ram不分页,采用连续存储的方式。反复进出,内存中产生大量的碎片,就无法继续使用了。


推荐阅读:
相关文章