2.1 内存硬件原理

4.1 内存物理结构

相信绝大多数的⼈都了解内存对⻬,都知道变量应该按8字节去对⻬,这样性能⾼。但是其最最底层的原理是啥呢? 有的⼈可能会说,因为⾼速缓存是以8字节为单位进⾏的。读者你很聪明,这是原因之⼀。但我今天想挖的是更底层⼀点的原理,让我们去内存的物理构成⾥找找答案!

内存物理结构

前⾯我们说过内存是由chip构成。每个chip内部,是由8个bank组成的。其构造如下图:

⽽每⼀个bank是⼀个⼆维平⾯上的矩阵,前⾯⽂章中我们说到过。矩阵中每⼀个元素中都是保存了1个字节,也就是8个bit。

内存编址⽅式

那么对于我们在应⽤程序中内存中地址连续的8个字节,例如0x0000-0x0007,是从位于bank上的呢?直观感觉,应该是在第⼀个bank上吗? 其实不是的,程序员视⻆看起来连续的地址0x0000-0x0007,实际上位于8个bank中的,每⼀个bank只保存了⼀个字节。在物理上,他们并不连续。下图很好地阐述了实际情况。

你可能想知道这是为什么,原因是电路⼯作效率。内存中的8个bank是可以并⾏⼯作的。 如果你想读取地址0x0000-0x0007,每个bank⼯作⼀次,拼起来就是你要的数据,IO效率会⽐较⾼。但要存在⼀个bank⾥,那这个bank只能⾃⼰⼲活,只能串⾏进⾏读取,需要读8次,这样速度会慢很多。

结论

所以,内存对⻬最最底层的原因是内存的IO是以8个字节64bit为单位进⾏的。对于64位数据宽度的内存,假如cpu也是64位的cpu(现在的计算机基本都是这样的),每次内存IO获取数据都是从同⼀⾏同⼀列的8个bank中各⾃读取⼀个字节拼起来的。从内存的0地址开始,0-7字节的数据可以⼀次IO读取出来,8-15字节的数据也可以⼀次读取出来。

再换个例⼦假如你指定要获取的是0x0001-0x0008,也是8字节,但是不是0开头的,内存需要怎么⼯作呢?没有好办法,内存只好先⼯作⼀次把0x0000-0x0007取出来,然后再把0x0008-0x0015取出来,把两次的结果都返回给你。 CPU和内存IO的硬件限制导致没办法⼀次跨在两个数据宽度中间进⾏IO。这样你的应⽤程序就会变慢,算是计算机因为你不懂内存对⻬⽽给你的⼀点点惩罚。

扩展

  • 事实上,编译和链接器会⾃动替开发者对⻬内存的,尽量帮你保证⼀个变量不跨列寻址。但是他不能做到⼗分完美。
  • 其实在内存硬件层上,还有操作系统层。操作系统还管理了CPU的⼀级、⼆级、三级缓存。不知道你有没有印象,我们前⾯的⽂章说过⾼速缓存⾥的Cache Line是64字节,它是内存IO单位的8倍,不会让内存IO浪费。

4.2 内存⼯作过程

平时⼤家都知道内存访问很快,今天来让我们来把刨根问底的精神发挥到极致,来思考两个问题:

  • 你是否会估算你的进程在访问内存的时候的延迟时间?
  • 内存存在随机IO⽐顺序IO慢的问题吗?

例如笔者的内存条的Speed 显示是1066MHz,那是否可以推算出内存IO延时是1s/1066MHz = 0.93ns?这种算法⼤错特错。

图书管理员的故事

在开始介绍枯燥的内存⼯作原理之前。我想先给你讲⼀个故事,并带你去认识⼀个⼈,图书馆的管理员。

在我们的这个故事中,你是故事的主⻆。你有⼀所房⼦,你每天需要在房⼦⾥处理各种各样的图书数据。但是北京房价太贵,所以你家房⼦很⼩,只能放的下64本书。你家的⻢路对⾯,就是北京图书馆(你家房⼦虽然⼩但是地段还不错),你所需要的所有的图书在那⾥都可以找到。你有⼀个仆⼈,他的职责就是帮你到你对⾯的图书管理取书。图书馆有个管理员,他负责帮你把你想要的书找出来。

好接下来,导演喊了action,场景开始!

场景1: 你发现你需要编号为0的书,你的仆⼈穿过⻢路告诉了图书管理员,告诉它请帮我把第0-63本书取出来。图书管理员帮你在电脑前查得该书在⼆楼。 于是他,花了点时间坐电梯到了⼆楼。等到了⼆楼,他⼜花了点时间帮你找了出来。然后你的仆⼈抱着64本书帮你放到了客厅。 你拿起第0本书处理了起来。

场景2: 你发现你需要编号为1的书,告诉你的仆⼈。你的仆⼈直接帮你从客厅就拿了出来,这次你等的时间最短。

场景3: 你发现需要编号为65的书,你⼜告诉你的仆⼈。你的仆⼈穿过⻢路⼜去找了图书管理员。图书管理员还在⼆楼呢,听说这次需要65-127,这次他不⽤再花时间找楼层了。只是花时间找书就可以了。你的仆⼈把65-127的书帮你放到了客厅(以前的0-63就都扔了)。你开始处理起65号书来。

场景4: 你发现你需要编号为10000的书,你告诉了你的仆⼈。你的仆⼈穿过⻢路去图书馆,找到了管理员。这次管理员查得你需要的书是在10楼,他得花点时间坐电梯过去。去了之后,他⼜得花点时间帮你找出来。

这四个场景⾥,我觉得你⼀定发现了不同情形下耗时的差异。

  • 场景1和场景4花费的时间最多。因为图书管理员需要花时间坐电梯找楼层,需要花时间在楼内找书。
  • 场景3次之,因为图书管理员直接就在楼层内,只需要花时间在楼内找书即可。
  • 场景2最快,因为只需要仆⼈帮你从客厅拿过来就好。

CPU和内存通信总过程

故事听完了,这个故事和内存IO过程相似度⾮常之⾼。相信⼀定有助于你理解下⾯的过程。

在现代的后端服务器,基本上都是NUMA架构了,前⾯⽂章《在你进程⾥不是所有内存条访问起来都⼀样快!》我们⽐较详细地说过FSB和QPI的区别,他们都是CPU和内存的桥接⽅式不同⽽已。由于我们本次⽂章的主要⽬的是让⼤家来了解CPU读取内存数据的过程,所以就先以最简单的FSB来进⾏讨论。实际上QPI的内存IO原理也类似,只不过砍掉了中⼼总线,这样CPU可以独⽴和⾃⼰内存IO了,总体上内存IO速度就上来了。但对于单条内存来讲,速度不会有任何变化。

在FSB总线的体系结构⾥,获取到内存数据的⼀个完整的过程如下:

  1. CPU需要把内存物理地址放到前端总线FSB
  2. 前端总线FSB把地址传递给芯⽚组
  3. 芯⽚组对DRAM进⾏寻址,和数据的读取
  4. 把读取完的数据放到前端总线上,供CPU读取

你现在应该能理解到了,上⾯的第3步芯⽚组对DRAM进⾏寻址,和数据的读取其实就相当于上⾯例⼦中图书管理员的⼯作。在内存的IO⾥,它的⼯作是最耗时的。因为现代的CPU要⽐内存快。

内存芯⽚组过程

那我们把这位“图书管理员”单独拿出来说道说道。在前⾯的⼩节⾥,你应该记得我们内存有CL-tRCD-tRP-tRAS四个参数。 我们先来简单认识⼀下这四个参数的含义:

  • CL (CAS Latency):发送⼀个列地址到内存与数据开始响应之间的周期数
  • tRCD (RAS-to-CAS Delay):打开⼀⾏内存并访问其中的列所需的最⼩时钟周期数
  • tRP (RAS Precharge Time):发出预充电命令与打开下⼀⾏之间所需的最⼩时钟周期数。
  • tRAS (RAS Active Time):⾏活动命令与发出预充电命令之间所需的最⼩时钟周期数。

要注意的是,上⾯的参数都是以时钟周期为单位的。因为现代的内存都是⼀个时钟周期上下沿分别各传输⼀次数 据,所以用Speed/2就可以得出时钟频率。例如笔者的机器的Speed是1066MHz,则时钟周期为667MHz。你⾃⼰的机器可以通过dmidecode命令查看:

# dmidecode | grep -P -A16 "Memory Device"
Memory Device
        ......
        Speed: 1067 MHz
        ......
  1. 内存模块⾸先要确定chip(物理可⻅的⿊⾊颗粒)
  2. 内存模块要经过tRAS个周期,使得该chip的⾏地址可以被选。
  3. 接下来发送⾏地址到指定chip下所有的bank,经过tRCD个周期,RAM可以成功锁定到要请求的内存⾏,并把内存⾏copy到⾏缓存中。(在tRCD的周期内,芯⽚同时会进⾏列地址选通和给地址线上放列地址,但由于这两步操作是可以并⾏在tRCD内完成,所以在统计耗时的⻆度,⼀般就不说这两步了)
  4. 接下来发送列地址指定chip下所有的bank,在CL个周期内,内存电路会在所有bank(8个)的rowbuffer中找到内存颗粒⼤⼩的数据(⼀般是8bit)。所有bank把数据汇总起来,就是⼀次64bit数据的结果。然后就可以输出数据到数据针脚了。

以上是描述的⼀个相对⽐较完整的内存寻址过程。 假如上述⼀次完整的过程之后的下⼀次内存IO是连续的话(⾏地址没变,只有列地址变了),那么下⼀次的内存IO只需要CL个周期即可(当然,还要外加上CPU往FSB放数据、取数据的时间)。所以说,对于内存来讲,和硬盘类似,也存在顺序IO⽐随机IO速度要快的效果。

题外话

对于连续的内存IO,除了第⼀个请求外,后⾯的tRAS、tRCD周期都是不需要的,只需要CL。有的内存⼚家⼲脆就不在产品上标示出其tRAS周期了,这也有点奸诈的嫌疑。

不同场景耗时估算

假如我的内存的参数如下:⼯作频率1066MHz,延迟参数7-7-7-24。那么我们再把剧本拿到内存的场景⾥演⼀演。

场景1:冷启动或者是⾏列地址都变(需要先坐电梯找楼层)

这个场景⾥,所有的耗时情况如下:

  • CPU和FSB来通信:1个周期
  • FSB和内存芯⽚通信:1个周期
  • tRAS⾏地址选通:24个周期
  • 锁定⾏tRCD:7个周期
  • CL列地址延迟:7个周期
  • 内存芯⽚放数据到FSB:1个周期

那么总共是需要41个内存周期,耗时 = 41 * 1s/1066MHz = 38ns。

这个耗时已经挺慢的了,你想象CPU⼀次C语⾔函数调⽤才需要1ns左右,这差了⼏⼗倍。

场景2:⾏地址不变,只变列地址(楼层不变,只找书)

这个场景⾥,不需要tRAS⾏地址选通,不需要tRCD选定⾏。所以实际耗时如下:

  • CPU和FSB来通信:1个周期
  • FSB和内存芯⽚通信:1个周期
  • CL列地址延迟:7个周期
  • 内存芯⽚放数据到FSB:1个周期

总共只需要10个周期,耗时 = 10 * 1s/1066MHz = 9.3ns。

看,内存IO如果⾏地址(楼层)不变,性能要快4倍左右。

回顾Cache Line

因为对于内存来说,随机IO⼀次开销⽐顺序IO⾼好⼏倍。所以操作系统在⼯作的时候,会尽量让内存通过顺序IO的⽅式来进⾏。做法关键就是Cache Line。当CPU发现缓存不命中的时候,实际上从来不会向内存去请求1个字节,8个字节这种。⽽是⼀次性就要64字节,然后放到⾃⼰的Cache中存起来。

⽤上⾯的例⼦来看,

  • 如果随机请求8字节:耗时是38ns
  • 如果随机请求64字节:耗时是38 + 7*9 = 100ns

开销也没贵多少,因为只有第⼀个字节是真随机IO,后⾯的7个字节都是顺序IO。⽽且取出来的数据后⾯⼤概率要⽤,所以计算机内部就这么搞了!


4.3 内存核⼼频率

从2001年DDR内存⾯世以来发展到2019年的今天,已经⾛过了DDR、DDR2、DDR3、DDR4四个⼤的规格时代了。内存的⼯作频率也从DDR时代的266MHz进化到了今天的3200MHz。这个频率在操作系统⾥叫Speed、在内存术语⾥叫等效频率、或⼲脆直接简称频率。这个频率越⾼,每秒钟内存IO的吞吐量越⼤。但其实内存有⼀个最最基础的频率叫核⼼频率,它是实际内存电路的⼯作时的⼀个振荡频率。它是内存⼯作的基础,很⼤程度上会影响内存的IO延迟。我今天想给⼤家揭开另外⼀⾯,这个叫核⼼频率的东东其实在最近的18年⾥,基本上就没有什么太⼤的进步。

内存Speed

在Linux上可以查看到你机器上内存的Speed。

# dmidecode | grep -P -A16 "Memory Device"
Memory Device
        Array Handle: 0x0009
        Error Information Handle: Not Provided
        Total Width: 72 bits
        **Data Width: 64 bits**
        Size: 8192 MB
        Form Factor: DIMM
        Set: None
        Loc续上:
 
#### 内存背后的秘密——核心频率
 
通过`dmidecode`我们只看到了内存的一个Speed,它是数据传输的频率.这个频率又叫Data Speed,或等效频率.各个商家在内存的销售页面上也把这个频率标在特别明显的位置,提醒消费者他家的内存有多快多快.但其实从内存条的技术参数上来讲,有个最为重要的频率,是**核心频率**,它是内存电路的振荡频率,是内存一切工作的基石.
 
我们来看一下各代内存的更全面详细的数据.
 
| 内存代 | 核心频率 (MHz) | 预取宽度 (Prefetch) | 时钟频率 (MHz) | 等效频率 Speed (MHz) | 数据传输率 (MT/s) |
|---|---|---|---|---|---|
| SDR | 133~200 | 1 | 133~200 | 133~200 | 133~200 |
| DDR | 133~200 | 2 | 133~200 | 266~400 | 266~400 |
| DDR2 | 133~200 | 4 | 133~200 | 533~800 | 533~800 |
| DDR3 | 133~200 | 8 | 133~200 | 1066~1600 | 1066~1600 |
| DDR4 | 133~200 | 8 (Bank Group) | 133~200 | 2133~3200 | 2133~3200 |
 
可以看出,**核心频率在过去的18年里几乎没有实质性进步**,一直徘徊在133MHz~200MHz之间.我们所看到的内存Speed是在这个核心频率的基础上,通过各种技术手段放大出来的.之所以我们感觉内存在越来越快,就是放大技术手段在不断进步而已.
 
- **SDR时代**:在最古老的SDR(Single Data Rate SDRAM)年代里,一个时钟脉冲只能在脉冲上沿时传输数据,所以也叫单倍数据传输率内存.这个时期内存的提升方法就是提升内存电路的核心频率.
- **DDR时代**:但是内存制造商们发现核心频率到了200MHz再提升的话,难度就很大了.所以在电路时钟周期内预取2bit,输出的时候就在上升期和下降期各传输一次数据.所以核心频率不变的情况下,Speed(等效频率)就翻倍了.
- **DDR2时代**:同样是在上下沿各传一次数据,但将Prefech提升为4,每个电路周期一次读取4bit.所以DDR2的Speed(等效频率)就达到了核心频率的4倍.
- **DDR3时代**:同样也是上下沿各传一次数据,进一步将Prefetch提升为8.所以DDR3的等效频率可以达到核心频率的8倍.
- **DDR4时代**:这时预取的提升已经非常困难,所以和DDR3一样,Prefetch仍然为8.内存制造商们又另辟蹊径,提出了**Bank Group设计**,允许各个Bank Group具备独立启动操作读、写等动作特性.所以等效频率可以提升到核心频率的16倍.
 
> [!note] 关于IO频率与时钟频率
> 
> 内存还有个概念叫IO频率、也叫时钟频率.简单理解为将DDR内存的Speed频率除以2,就是内存的IO频率.这个必须和CPU的外频相匹配才能工作.例如对于DDR3来说,假如核心频率133MHz的内存工作频率下,匹配533MHz的CPU外频,其IO频率就是533MHz.数据传输因为上下沿都可以传,所以是核心频率的8倍,也就是1066MHz.
 
我曾试图在Linux下找到能查看核心频率和IO频率的命令,但是没有找到,在售的各种内存条似乎也很少会提及它.但我们是IT从业人员,非普通用户,因此我觉得大家有必要来了解这个原理.(事实上,这两个频率会影响后面讨论的内存的延迟参数,而延迟参数又决定了内存的真正性能)
 
**一句话总结:内存真正的工作频率是核心频率,时钟频率和数据频率都是在核心频率的基础上,通过技术手段放大出来的.内存越新,放大的倍数越多.** 但这些放大手段都有一些局限性——比如你的内存数据存储并不连续,这时候DDR2、DDR3的数据预取对你帮助并不大;再比如你的进程数据都存在一个Bank Group里,你的进程内存IO就根本不会达到DDR4厂家宣传的速度.
 
---
 
#### 扩展知识:内存延迟
 
除了频率以外,内存还有几个比较重要的参数,但同样在Linux里没有找到查看的命令.内存的销售页面想找到这几个参数也不是特别容易.
 
所有的内存条都有 **CL-tRCD-tRP-tRAS** 四个参数.其中最重要的是 **CL-tRCD-tRP** 这三个参数,只要你费点劲,所有的在售内存你都能找到这3个值.例如经典的DDR3-1066、DDR3-1333及DDR3-1600的CL值分别为7-7-7、8-8-8及9-9-9.现在京东上一条比较流行的台式机内存金士顿(Kingston) DDR4 2400 8G,其时序是17-17-17.
 
第四个参数(tRAS)有时候会被省略.原因有二:
1. 现在的开发者不需要直接和内存打交道,而操作系统呢又做得比较内存友好,很少会有这个开销真正发生.
2. 这个开销的值要比其它的值大很多,实在不太好看.商家为了内存能多卖一些,干脆就避而不谈了.
 
好了,问题来了:**为什么内存越进步,延迟周期反而会变大了呢?**
 
这是因为延迟周期使用延迟时间除以内存时钟周期(Speed/2)算出来的.这其实不算太科学,最直接的办法应该用延迟时间来评估.延迟时间很大程度上是受内存的核心频率的制约的.而这些年来核心频率又基本上没有进步,所以延迟时间也不会有实质的降低.假定延迟时间不变,而时钟周期翻倍了,这样延迟周期看起来就是新的内存更大.
 
**一句话总结:内存的绝对延迟(纳秒级)并没有随着代际升级而显著降低,核心频率的瓶颈决定了延迟时间的物理极限.** 这也就是为什么很多高性能应用对内存延迟敏感,单纯提高频率并不能解决所有问题.
 
# 4.2 内存工作过程
 
## 图书管理员的故事
 
为了形象地理解内存的访问延迟,我们先用一个类比:你有一所只能放64本书的小房子,对面是藏书丰富的北京图书馆.你有个仆人负责去图书馆取书,图书馆有位管理员负责找书.
 
- **场景1(冷启动):** 需要第0本书.仆人告诉管理员要0-63本书,管理员查得在二楼,坐电梯上楼,花时间找到,仆人抱回64本书.你拿起第0本处理.
- **场景2(命中缓存):** 需要第1本书,仆人直接从客厅拿给你,最快.
- **场景3(行不变):** 需要第65本书.仆人找管理员,管理员还在二楼,知道65-127也在二楼,只需花时间找书,不用再找楼层.仆人抱回65-127本书(之前的0-63丢掉).你处理第65本.
- **场景4(远程/跨层):** 需要第10000本书.管理员查得到在10楼,坐电梯上去,找书返回.
 
不同场景耗时差异明显:场景1和4最长(坐电梯+找书),场景3次之(只找书),场景2最快(直接取).
 
## CPU和内存通信总过程
 
现代服务器多为NUMA架构(此前有FSB前端总线).以FSB为例(QPI原理类似但去掉中心总线):
 
1. CPU将物理地址放到前端总线FSB
2. FSB将地址传递给芯片组
3. 芯片组对DRAM寻址并读取数据
4. 数据通过FSB返回CPU
 
其中第3步(芯片组对DRAM的寻址)耗时最大,相当于图书管理员的工作.
 
## 内存芯片组过程
 
内存有四个关键延迟参数(以时钟周期为单位):
 
| 参数 | 全称 | 含义 |
|------|------|------|
| CL | CAS Latency | 发送列地址到数据开始响应之间的周期数 |
| tRCD | RAS-to-CAS Delay | 打开一行并访问其中的列所需的最小周期数 |
| tRP | RAS Precharge Time | 发出预充电命令与打开下一行之间的周期数 |
| tRAS | RAS Active Time | 行活动命令与发出预充电命令之间的周期数 |
 
现代内存一个时钟周期上下沿各传一次数据,所以时钟频率 = Speed / 2.可通过 `dmidecode` 查看 Speed:
 
```bash
# dmidecode | grep -P -A16 "Memory Device"
Speed: 1067 MHz

寻址步骤:

  1. 确定 chip(物理颗粒)
  2. 经过 tRAS 周期使该 chip 的行地址可被选
  3. 发送行地址到所有 bank,经过 tRCD 周期锁定行,并将行数据复制到行缓存
  4. 发送列地址,经过 CL 个周期,从所有 bank(8个)的行缓存中取出 8bit,汇总为 64bit 数据输出

若下一次 IO 的行地址不变(仅列地址变化),则只需 CL 个周期(加上CPU放地址、取数据的时间).因此内存也存在顺序IO比随机IO快的现象(类似硬盘).

不同场景耗时估算

假设内存参数:工作频率 1066MHz,延迟参数 7-7-7-24.

场景1:冷启动或行列地址都变(需坐电梯找楼层)

步骤周期数
CPU和FSB通信1
FSB和内存芯片通信1
tRAS行地址选通24
锁定行 tRCD7
CL列地址延迟7
内存芯片放数据到FSB1
合计41 周期

耗时 = 41 × (1s / 1066MHz) ≈ 38 ns.这比一次C语言函数调用(约1ns)慢几十倍.

场景2:行地址不变,只变列地址(楼层不变,只找书)

步骤周期数
CPU和FSB通信1
FSB和内存芯片通信1
CL列地址延迟7
内存芯片放数据到FSB1
合计10 周期

耗时 = 10 × (1s / 1066MHz) ≈ 9.3 ns.比随机IO快约4倍.

回顾 Cache Line

为了充分利用顺序IO的优势,CPU每次从内存读取数据时不是以字节为单位,而是以 Cache Line(通常64字节)为单位.即使只请求1个字节,也会一次取回64字节放入缓存.

  • 若随机请求8字节:耗时约38 ns
  • 若随机请求64字节:耗时约38 + 7×9 = 100 ns(只有第一个字节是真的随机IO,后续7个是顺序IO)

取回的数据后续大概率被用到,因此这种策略极大提升了效率.

缓存层次

L1、L2、L3 缓存的存在使得大部分内存访问落在高速缓存中,实际感知的延迟远低于内存原始延迟.参见8.2 CPU之高速缓存.

4.3 内存核心频率

内存 Speed

通过 dmidecode 可查看每根内存条的 Speed(数据传输频率)和 Data Width(数据位宽).

# dmidecode | grep -P -A16 "Memory Device"
Speed: 1067 MHz
Data Width: 64 bits

带宽 = Speed × Data Width。历代内存规格如下:

世代典型 Speed带宽
DDR266 MHz2.1 GB/s
DDR2533 MHz4.3 GB/s
DDR31066 MHz8.5 GB/s
DDR43200 MHz25.6 GB/s

内存背后的秘密 – 核心频率

内存实际电路工作的振荡频率称为核心频率(Core Frequency),多年来一直徘徊在 133~200 MHz 之间,受物理材料限制几乎停滞。我们所见的 Speed 是在核心频率基础上通过预取(Prefetch)等技术放大得到的。

世代核心频率预取倍数等效频率(Speed)
SDR133~200 MHz1133~200 MHz
DDR133~200 MHz2266~400 MHz
DDR2133~200 MHz4533~800 MHz
DDR3133~200 MHz81066~1600 MHz
DDR4133~200 MHz8(+Bank Group)2133~3200 MHz
  • SDR:单倍数据传输,一个时钟脉冲只在上升沿传输数据。
  • DDR:在上下沿各传一次数据,预取 2bit,等效频率 = 核心频率 × 2。
  • DDR2:预取 4bit,等效频率 = 核心频率 × 4。
  • DDR3:预取 8bit,等效频率 = 核心频率 × 8。
  • DDR4:预取仍为 8bit,但引入 Bank Group 设计,允许各组独立操作,等效频率可达核心频率 × 16。

局限性

若数据存储不连续(随机访问),预取技术帮助不大;若进程数据集中在一个 Bank Group,实际带宽远达不到理论值。

扩展知识:内存延迟参数

所有内存条都有 CL-tRCD-tRP-tRAS 四个参数(第四个有时省略)。常见的例子:

  • DDR3-1066:CL 7-7-7
  • DDR3-1333:CL 8-8-8
  • DDR3-1600:CL 9-9-9
  • DDR4-2400:CL 17-17-17

为什么内存越进步,延迟周期反而变大?

因为延迟时间 = 延迟周期 × 时钟周期。核心频率多年未变,导致延迟时间(纳秒)基本不变。而时钟周期(Speed/2)翻倍,所以延迟周期数值增大。

实际延迟

延迟时间才是衡量内存真实性能的关键,但由于核心频率停滞,现代内存的绝对延迟(纳秒)并未明显优于早期 DDR3。参见6.1 内存延时实测