大页面内存引起的杯具

内存是计算机中的珍贵的稀有资源,因此为了精细管理,内存管理非常复杂的,一台计算机会同时运行很多应用,以防止这些应用程序争抢内存,内存的管理是通过操作系统来管理的,操作系统为了方便管理内存,也为了降低应用程序使用的内存的复杂性,约会了虚拟内存的概念(还是那句话,解决不了的问题约会一个中间层)。

一虚拟内存

虚拟内存,可以看成内存和磁盘的抽象,通过中断,地址翻译,内存,磁盘文件,内核软件等交互,为每个应用程序均提供一个私有的大的地址空间。

在32位系统上,虚拟内存可以访问的存储空间为:2^32;64位系统中虚拟存储地址空间范围不是2 ^64,而是一般为:2 ^48, 因为现在还用不了这么大的空间,可以通过命令:

[root@izbp14xswj2tx6qgnz9dllz ~]# cat /proc/cpuinfo 
......
address sizes : 46 bits physical, 48 bits virtual
power management:

结果中:

address sizes : 46 bits physical, 48 bits virtual

表示物理地址为:46位,虚拟地址为48位。

这么大的空间是如何划分的那:

虚拟内存采用页为单位进行存储管理的,典型的页面大小为4KB或1MB,linux下可以通过getconf命令查看。有些特殊的场景比如需要大内存情况下,喜欢设置超级大页,而不是在DPDK这种高性能网络处理库中,常设置大页为1GB,目的是为了减少页表的压缩,可以让页表完全保存的高速缓存中,提高内存分配效率。

虚拟内存毕竟是虚的,在使用的时候系统会判断对应此虚拟内存页是否有映射的物理内存,如果没有对应的物理内存页,就会发生缺页中断,操作系统就会给这个虚拟内存页分配真正的物理内存,建立映射关系;如果现在物理内存也使用紧张,操作系统就会将不活跃的页换出存到磁盘的交换空间,将物理内存页释放出来,以供使用;如果下次换出的页面需要使用了,又会产生缺页中断,被换成到物理内存中,就这样来回倒腾,由于应用具有局部性,所以一般情况下,应用程序只在少量页面上工作,效率并不低。

[root@localhost ~]# cat /proc/swaps
Filename                Type        Size    Used    Priority
/dev/dm-1                               partition   2097148 0   -1
[root@localhost ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           2.8G        155M        2.4G        9.8M        234M        2.4G
Swap:          2.0G          0B        2.0G
[root@localhost ~]# swapon -s
文件名             类型      大小  已用  权限
/dev/dm-1                               partition   2097148 0   -1

二地址翻译

刚才说了,我们应用使用的是虚拟内存,真正使用的时候才会通过操作系统,MMU(内存管理单元)和存在内存中的页表结合来完成虚拟地址和物理地址的翻译工作。页表将虚拟地址映射为物理地址,如下图:

实际情况要更复杂,某些分了多级页表,多级页表可以减少内存的使用,例如在x86的32位地址上通过二级页表完成地址的翻译。

这些页表是保存在内存中的,如果每次都要这么翻译,内存访问的性能肯定是受到一定影响的,数据都可以缓存,页表页同样可以进一步缓存放在SRAM中,MMU中有关于页表的缓存,小的缓存称为TLB(后备缓存),加入TLB后,翻译就如下图:

如果有4GB虚拟内存空间,每个页面大小为4K,那就有2^20个页表项,好了问题来了,TLB是一个小的缓存,保存的映射页表项毕竟是有限的。 如果在页表中一个页表项占用4个字节,那么4G虚拟空间对应的页表大小就为4B * 1M即4MB大小的空间,因为页表是每个程序单独拥有的,所以TLB肯定存不下。

页表大小= 页表项个数*页表项大小

按照上公式,如果我们的整个页表都可以保存到TLB中,将提升内存的访问速度,从几十到几百个时钟周期,降低到1到2个时钟周期,页表项的大小一般是固定不变的, TLB的大小也不变,所以我们只能想办法减少页表项的个数。

页表项的个数= 总内存/一个内存页大看来,如果我们增加内存页的大小,则我们设置内存页大小为1GB,那么4GB的内存,只需要4个页表项,很容易将整个页表都保存在TLB中,从而提高内存的访问速度。

三大页内存

上面提到,我们为了提高内存访问速度,我们对于耗费很大的应用程序使用Oracle等,可以采用大页内存方式,如果程序本身使用的内存很少,采用大页内存效果不明显,还浪费了内存。

3.1查看是否支持

Linux系统采用hugetlbfs的特殊文件系统来加入对2MB和1GB的大页内存的支持,为了配置,先查看cpu是否支持:

 cat  /proc/cpuinfo |grep --color pse
 cat  /proc/cpuinfo |grep --color pdpe1gb

查看内核是否支持:

 grep  -i hugetlb /boot/config-4.18.0-193.el8.x86_64 
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_CGROUP_HUGETLB=y
# 以下两种都为y则标识支持
CONFIG_HUGETLBFS=y 
CONFIG_HUGETLB_PAGE=y

cpu的功能列表中包含pse标识支持2MB的内存大页,包含pdpe1gb支持1GB的内存大页。

3.2查看大页内存使用情况

grep Huge /proc/meminfo
AnonHugePages:   4089856 kB
ShmemHugePages:        0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB

这里面说明:

一个页面大小为:Hugepagesize: 2048 kB

内存大页数量为:HugePages_Total: 0

NUMA架构的查看:

[root@localhost ~]# cat /sys/devices/system/node/node*/meminfo|fgrep Huge
Node 0 AnonHugePages:    153600 kB
Node 0 HugePages_Total:     0
Node 0 HugePages_Free:      0
Node 0 HugePages_Surp:      0
Node 1 AnonHugePages:     30720 kB
Node 1 HugePages_Total:     0
Node 1 HugePages_Free:      0
Node 1 HugePages_Surp:      0

可以看到这个NUMA机器上并没有分配大页内存:

HugePages_Total: 0

3.3分配大页内存

如果分配2MB的大页内存比较简单,可以通过命令替换:

echo 1024> /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

分辨率1024个2MB的大页即复制2GB的大页内存。

如果是NUMA架构,在每个先前附上的添加:

echo 1024> /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 1024> /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages

如果要分配超过1GB的大页内存,需要在Linux的启动项中设置和挂载。1)安装

yum install libhugetlbfs

2)分配更改启动文件,添加:

transparent_hugepage=never default_hugepagesz=1G hugepagesz=1G hugepages=4

分配4个大页内存,每个为1G,在centos6中是修改

/etc/grub.conf

centos7修改英文/etc/grub2.cfg文件。3)挂载将大页内存映射到空目录:

mkdir    /mnt/myhuge
mount -t hugetlbfs nodev /mnt/myhuge

如果要开机自动设置:

vim /etc/fstab
nodev /mnt/myhuge hugetlbfs pagesize=1GB 0 0

像DPDK等有专门的设置工具,开机的时候立即设置防止内存不足,大页内存需要连续的空间。

3.4程序使用

#这个是看资料查的,并没有实践过
HUGETLB_MORECORE=yes   LD_PRELOAD=libhugetlbfs.so     ./your_program

四大页优缺点

优点:

1)大页内存的页表小很多,可以放入到TLB中,缺页中断也很少,对于内存的访问性能更好,对于占用大量内存的程序,性能提升比较明显,有的甚至可以提升到50%左右。

2)大页内存的内存页不会交换到磁盘上。

缺点:   

1)必须使用特定的方式使用,并采用mmap映射或通过上面的方式指定。

2)程序使用内存小,却申请了大页内存,会造成内存浪费,因为内存分配最小单位是页。

3) 如果使用不当,可能白白浪费内存,其他程序无法使用大页内存。

五大页面内存引起的杯具

说了半天,还没有说到到大页内存导致了什么杯具那,是这样的,在一台机器上,内存本来就很小,只有4GB内存。

用Top命令查看程序内存只有不到1G的占用,当时剩余内存只有300MB,剩余内存哪里去了?

分析下内存分配:

# cat /proc/meminfo|grep Huge
HugePages_Total:    1035
HugePages_Free:     1033
HugePages_Rsvd:       62
HugePages_Surp:        0
Hugepagesize:       2048 kB

更好的工具是用atop查看,发现大页内存占用了了高达2GB的内存,却没怎么使用。

解决办法

#禁用大页缓存
vi /etc/sysctl.conf

vm.nr_hugepages = 0
vm.nr_hugepages_mempolicy = 0

# 生效
sysctl -p

命令执行完毕后,起到了立竿见影的效果,一下释放了2GB的内存,这可是占系统的内存一半啊,所以大页内存是否使用,还要斟酌,不然白白浪费了内存。

如果程序内存占用大,TLB的miss却很多的情况下,可以使用,具体如何查看TLB的miss多那,可以通过性能工具来进行分析:

perf record -e dTLB-loads -e faults -p pid
perf report

六 诗词欣赏

 竹里馆  - - [王维]

独坐幽篁里,弹琴复长啸。
深林人不知,明月来相照。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值