置信绝大多数的人都理解内存对齐,都晓得变量应该按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个chip中各自读取一个字节拼起来的。从内存的0地址开始,0-7字节的数据能够一次IO读取进去,8-15字节的数据也能够一次读取进去。
再换个例子如果你指定要获取的是0x0001-0x0008,也是8字节,然而不是0结尾的,内存须要怎么工作呢?没有好方法,内存只好先工作一次把0x0000-0x0007取出来,而后再把0x0008-0x0015取出来,把两次的后果都返回给你。 CPU和内存IO的硬件限度导致没方法一次跨在两个数据宽度两头进行IO。这样你的应用程序就会变慢,算是计算机因为你不懂内存对齐而给你的一点点惩办。
扩大1:事实上,编译和链接器会主动替开发者对齐内存的,尽量帮你保障一个变量不跨列寻址。然而他不能做到非常完满。扩大2:其实在内存硬件层上,还有操作系统层。操作系统还治理了CPU的一级、二级、三级缓存。不晓得你有没有印象,咱们后面的文章说过高速缓存里的Cache Line也是64字节,它是内存IO的整数倍,不会让内存IO节约。
开发内功修炼之内存篇专辑:
- 1.带你深刻了解内存对齐最底层原理
- 2.内存随机也比程序拜访慢,带你深刻了解内存IO过程
- 3.从DDR到DDR4,内存外围频率其实基本上就没太大的提高
- 4.理论测试内存在程序IO和随机IO时的拜访延时差别
- 5.揭穿内存厂家“谎话”,实测内存带宽实在体现
- 6.NUMA架构下的内存拜访提早区别!
- 7.PHP7内存性能优化的思维精华
- 8.一次内存性能晋升的我的项目实际
- 9.挑战Redis单实例内存最大极限,“遭逢”NUMA陷阱!
我的公众号是「开发内功修炼」,在这里我不是单纯介绍技术实践,也不只介绍实践经验。而是把实践与实际联合起来,用实际加深对实践的了解、用实践进步你的技术实际能力。欢送你来关注我的公众号,也请分享给你的好友~~~