内存管理发展阶段
内存(RAM)是计算机一种重要资源, 随着应用越来越复杂,不管存储器有多大,程序都可以把他填满
,这就迫使人们不断寻找解决方案去管理它.
内存管理经历的几个阶段;
- 无存储抽象阶段 (No Memory abstraction)
- 地址空间 (Address Spaces)
- 虚拟内存 (Virtual Memory)
- 无存储抽象阶段: 直接使用物理地址, 简单和划分了用户和操作系统,(驱动程序)使用的内存. 早期的MSDOS采用这种管理方案。
- 通过每个进程基址寄存器和界限寄存器实现动态重定位,映射到不通的物理内存。通过交换技术和空闲内存管理, 处理内存超载
- 构建虚拟地址空间,通过MMU(内存管理单元)完成虚拟内存与物理内存的映射。
分页
分页就是出现虚拟内存这个阶段.虚拟地址按照固定大小划分成若干个页面Page, 物理内存中对应为页框 Page Frame (物理内存最小数据单位), 当程序试图访问内存时,MMU根据虚拟地址映射为物理地址.
页面大小
不同处理器体系结构页面大小
体系结构 | 最小页面 | 支持大页面 |
---|---|---|
32-bit x86 | 4 KiB | 4 MiB, 2 MiB |
x86-64 | 4 KiB | 2 MiB, 1 GiB |
IA-64 (Itanium) | 4 KiB | 8 KiB, 64 KiB, 256 KiB, 1 MiB, 4 MiB, 16 MiB, 256 MiB |
Power ISA | 4 KiB | 64 KiB, 16 MiB, 16 GiB |
SPARC v8 with SPARC Reference MMU | 4 KiB | 256 KiB, 16 MiB |
ARMv7 | 4 KiB | 64 KiB, 1 MiB , 16 MiB |
UltraSPARC Architecture 2007 | 8 KiB | 64 KiB, 512 KiB , 4 MiB, 32 MiB, 256 MiB, 2 GiB, 16 GiB |
页面大小考虑因素(wiki)
页面大小通常有处理器体系结构决定, 目前常用页面大小4KB。选择最佳页面大小要考虑一下几个因素:
- 页表大小: 页面越小时系统需要更多的页面.
- TLB使用: 页面大小越大,TLB可以跟踪更大内存.
- 内部碎片:较大的页面大小会导致大量的内存浪费
- 磁盘存取 页面越大相同数据磁盘传输到内存通常需要时间更少.
页面大小设置其他一些考量方式
最优页面计算数学公式
现代操作系统书中页面最优公式描述:
平均进程大小为s
个字节,页面大小为p
个字节。此外,假设每个页面条目都需要e
个字节。每个进程所需的大概页面数为s/p, 占用页表空间的se/p字节。 最后一页的内存浪费 内部碎片 p/2。 因此,由于 页表和内部碎片损失由总和得出
$$总开销 = s*e/p + p/2$$
在页面比较小的时候页表项大, 页面比较大的时候内部碎片大, 页面大选主语中间的某个值, 求导数后得出最优页面大小:
$$−s*e/p^2 + 1/2 = 0$$
得到最优页面大小公式
$$p = \sqrt{2s*e}$$
当 s=1MB 每个页表项 e=8B,最优页面大小为 4KB(以前典型值为1KB)
其他有趣的算法
stackoverflow 的一个帖子 Why is the page size of Linux (x86) 4 KB, how is that calculated?
x86使用2级页表
将虚拟内存地址转换为物理内存地址。 因此,假设页面目录和页面表都包含 2^x 项, 并且页面大小2^y字节。 为了充分利用 2^32 地址空间,我们有:
$$2^{x}2^{x}2^{y} = 2^{32} => 2x+y=32$$
页面目录/表中的每个条目占用4个字节(32位),因此:
$$2^{y}/4 = 2^{x} => y-2 =x $$
y = 12 页面大小 2^y=4KB
同理下面是X86_64页面计算方法,与X86不同的是使用了四级页表, 48位用于寻址:
$$2^x 2^x 2^x 2^x 2^y = 2^{48} =>4x + y = 48 $$
每个地址 8 bytes (8 bytes * 8 bits / byte = 64 bits)
$$2^y / 2^3 = 2^x => y – 3 = x $$
y = 12 页面大小 2^y=4KB
Linux Huge Page
通过处理器体系结构的支持可以根据需要将页面大小增加,以期待获得更高的效率.
相关参数
内核配置参数
- CONFIG_HUGETLBFS
- CONFIG_HUGETLB_PAGE
内核Huge信息
- /proc/meminfo
参数 | 说明 |
---|---|
HugePages_Total | 总页面数量 |
HugePages_Free | 未使用页面数量 |
HugePages_Rsvd | 应用申请未使用数量 |
HugePages_Surp | 超过常驻页面使用数量,动态调整方式 |
Hugepagesize | 每个页的大小单位Kb |
Hugetlb | 占用内存大小(kB)相当于 HugePages_Total * Hugepagesize |
关于参数说明可以参考以下两篇文章:
Linux下hugetlbpage使用详解
HugePages_Rsvd 是什么意思?
修改方法
修改sysctl参数
以 Cenos6,7 / RHEL4,5为例
1 设置
# vi /etc/sysctl.conf
vm.nr_hugepages = 10
# sysctl -p
vm.nr_hugepages = 10
或临时修改
echo 10 > /proc/sys/vm/nr_hugepages
2 验证
cat /proc/meminfo|grep Huge
HugePages_Total: 10
HugePages_Free: 10
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 20480 kB
启动时设置
通过修改grub2参数实现
1 修改/etc/default/grub
GRUB_CMDLINE_LINUX="... hugepages=10 hugepagesz=2M default_hugepagesz=4M"
2 使用grub2-mkconfig 重建 grub.cfg
[root@centosgpt ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
3 验证
cat /proc/meminfo|grep Huge
HugePages_Total: 10
HugePages_Free: 10
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 20480 kB
参考
wiki Page (computer memory)
Why is the page size of Linux (x86) 4 KB, how is that calculated?
CentOS / RHEL 6,7 : How to configure hugepages
CONFIGURING HUGE PAGES IN RED HAT ENTERPRISE LINUX 4 OR 5
Be First to Comment