内存管理 – 页面大小

内存管理发展阶段

内存(RAM)是计算机一种重要资源, 随着应用越来越复杂,不管存储器有多大,程序都可以把他填满,这就迫使人们不断寻找解决方案去管理它.

内存管理经历的几个阶段;

  • 无存储抽象阶段 (No Memory abstraction)
  • 地址空间 (Address Spaces)
  • 虚拟内存 (Virtual Memory)
  1. 无存储抽象阶段: 直接使用物理地址, 简单和划分了用户和操作系统,(驱动程序)使用的内存. 早期的MSDOS采用这种管理方案。
  2. 通过每个进程基址寄存器和界限寄存器实现动态重定位,映射到不通的物理内存。通过交换技术和空闲内存管理, 处理内存超载
  3. 构建虚拟地址空间,通过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

发表评论

电子邮件地址不会被公开。 必填项已用*标注