RHCA rh442 007 hugetlbfs strace命令追踪 脏页设置 内存分配
内存管理
虚拟内存 --- 物理内存
应用程序申请虚拟内存 --- RAM + SWAP (真正主板上的设备)
他们之间有一张映射表 page table 页表
PTE: 页表条目 虚拟内存和物理内存的映射关系
每一条的条目叫PTE
cpu MMU 内存管理单元
虚拟内存与物理内存之间做映射的管理单元
TLB 大页 给PTE提供缓存, 从内存中分配, 从内存中分配一段区域来缓存PTE记录
下次打开从缓存TLB里面调用,不需要通过mmu重新分配
sysctl -a | grep huge
过滤大页选项
cat /proc/meminfo
查看内存内容
大页是一段连续的地址空间,一段分配,大页不使用,空间也被占用了。默认情况系统不使用大页,大页用来记录PTE的缓存
[root@workstation ~]# lab memtuning-paging start
实验
[root@servera ~]# vi /etc/sysctl.conf
[root@servera ~]# sysctl -p
vm.swappiness = 15
vm.nr_hugepages = 100
[root@servera ~]#
[root@servera ~]#
[root@servera ~]#
[root@servera ~]# cat /proc/meminfo | grep -i huge
AnonHugePages: 16384 kB
ShmemHugePages: 0 kB
HugePages_Total: 100
HugePages_Free: 100
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 204800 kB
申请100M的大页
[root@servera ~]# bigmem -H 100M
Process PID: 5928
Allocating 100 MiB of huge pages (50 pages)
Assuming 2 MiB huge pages...
Done
[root@servera ~]# cat /proc/meminfo | grep -i huge
AnonHugePages: 16384 kB
ShmemHugePages: 0 kB
HugePages_Total: 100
HugePages_Free: 50
HugePages_Rsvd: 0
vm.nr_hugepages = 100
大页数
一个大页2048k
大页一共大小 200M
分配大页让cpu更节省资源
大页很难设置好,所以
透明大页
当你需要大页时,系统动态分配大页
[root@servera transparent_hugepage]# cat enabled
[always] madvise never
[root@servera transparent_hugepage]# pwd
/sys/kernel/mm/transparent_hugepage
[root@servera transparent_hugepage]#
[root@servera transparent_hugepage]# echo never > enabled
[root@servera transparent_hugepage]# pwd
/sys/kernel/mm/transparent_hugepage
[root@servera transparent_hugepage]# cat enabled
always madvise [never]
[root@servera transparent_hugepage]#
madvise 触发式 (在特殊情况下)
THP(透明大页)在某些场景会出现异常 Oracle MongoDB Redis 可能导致延迟和内存使用问题
Oracle MongoDB Redis
大内存使用,内存消耗大户
数据库调优首先关闭透明大页
华为的虚拟化用到了透明大页和NUMA
大页的设置参照这个公式比较好
内核参数
hugepages=整数
hugetlbfs
如果你的应用程序需要调用大页那你就得配置hugetlbfs (应用程序包含mmap调用)
那你就得需要配置虚拟文件系统
有没有你都把它挂上就好了
nodev hugetlbfs /hugetlbfs defaults 0 0
mkdir /my-hugepages
mount -t hugetlbfs none /my-hugepages
这个设备名去 /proc/filesystems里面看
追踪可以查看到命令里的mmap
strace 追踪
-c 统计
[root@foundation0 ~]# strace -c cp -r /etc/ /tmp
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
19.07 0.191608 59 3216 13 openat
18.06 0.181443 62 2917 read
13.53 0.135940 53 2527 lstat
13.16 0.132202 41 3206 close
12.23 0.122903 38 3203 fstat
7.83 0.078694 51 1526 write
5.08 0.051012 37 1374 fadvise64
3.62 0.036399 42 864 getdents64
3.49 0.035071 81 432 mkdir
2.39 0.023991 83 289 symlinkat
1.19 0.011930 41 289 readlink
0.16 0.001571 43 36 mmap
0.07 0.000675 42 16 mprotect
0.03 0.000325 36 9 1 lseek
0.02 0.000207 103 2 statfs
0.01 0.000112 22 5 brk
0.01 0.000090 45 2 munmap
0.01 0.000073 36 2 umask
0.01 0.000070 70 1 rt_sigprocmask
0.01 0.000070 70 1 prlimit64
0.01 0.000055 55 1 futex
0.01 0.000052 26 2 rt_sigaction
0.00 0.000048 48 1 1 newfstatat
0.00 0.000046 23 2 1 access
0.00 0.000040 40 1 stat
0.00 0.000038 38 1 sysinfo
0.00 0.000037 37 1 geteuid
0.00 0.000037 18 2 1 arch_prctl
0.00 0.000035 35 1 set_robust_list
0.00 0.000025 25 1 set_tid_address
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 1.004799 19931 17 total
time 多少的时间在干什么
calls 调用多少次
usecs/call 每次系统调用所花的微妙
second = usecs x call
追踪这命令做了什么
[root@foundation0 ~]# strace -e openat cp -r /etc/ /tmp
追踪这个命令做了什么打开的操作
案例
strace -e open ssh 192.168.6.22
有时ssh 连接会很慢
尝试strace跟踪,然后-e open
查看这个ssh读到的这个文件
nsswithch.conf:服务搜索顺序
文件/etc/nsswitch.conf(name service switch configuration,名字服务切换配置)规定通过哪些途径以及按照什么顺序通过这些途径来查找特定类型的信息。还可以指定某个方法奏效或失效时系统将采取什么动作。
可以发现他先从host表里面找,然后再从dns里面找
ssh 查dns,(因为ssh加密)加密通常和计算机名有关。通常给计算机名加密。ssh反查ip地址对应的计算机名是谁,查半天查不到 (etc/hosts lib_files.so.2)调整etc/hosts就可以也可以不做dns查询
目标主机不要做dns查询
[(本地的也可以改一改)]
简单的ls命令系统也做了很多工作,打开了很多文件
resident memory(物理内存) 和 virtual memory(虚拟内存)
内存过量分配
内存复用
华为内存复用150%
虚拟机的内存加起来超过宿主机
[root@servera /]# sysctl -a | grep overcom
vm.nr_overcommit_hugepages = 0
vm.overcommit_kbytes = 0
vm.overcommit_memory = 1 #默认0
vm.overcommit_ratio = 50 #默认50
vm.overcommit_memory
0 有多少就分配多少 (没有就没有)
1 总是过量分配 (瞬间很高,是可以接受的,这一瞬间,应用程序会很慢。总是过量那就会有问题)
2 平衡值 可以分配的虚拟内存为SWAP + RAM * 50%
设为2
vm.overcommit_ratio = 50 这个值才有意义
这个是比率可以调整
调高了对性能还是会有影响
测试
bigmem -b
swap对于应用程序来说也是物理内存
缓存
内存页状态
used 被使用不能分配
free 立即可分配
buff/cache clean page 可以释放,干净的页 它没有被改变,或者已经同步到磁盘
Dirty 已经改变,没有写到磁盘
回收脏页
后端有pdflush 监控内存页并回收
[root@servera ~]# sysctl -a | grep dirty
vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 40
vm.dirty_writeback_centisecs = 500
vm.dirtytime_expire_seconds = 43200
vm.dirty_expire_centisecs 脏页老化时间
脏页的过期时间,3000 = 1/100 秒 =30秒
没回收数据就丢了,不进硬盘
写到脏页是为了写缓存
写缓存,聚合io: 提升写性能
脏页不宜过长,容易丢失数据
如果写入的数据是随机的小IO,则建议将脏页老化时间设置得更长一些,让数据得以更多的聚合,反之,如果数据是连续的IO或者大IO,256K直接下发,不经过缓存
watch -n 1 'cat /proc/meminfo | grep Dirty'
拷贝数据,然后可以测出,确实是30m
vm.dirty_ratio 脏页站整个内存的比率
脏页占整个内存的比率 64G 32G = 50%
低水位: 当脏页的数量达到整个内存40%时,即便没有到老化时间,也会立即回收脏页
10%
来不及聚合就被回收
80%
脏页一直没回收,直到耗尽内存 波动大
384G*40% 那脏页也特别大啊
vm.dirty_bytes = 0
0为不关注
可以设置脏页达到10G时,会立即回收
vm.dirty_writeback_centisecs = 500
5秒监控一次,是否达到这个值
vm.dirty_background_ratio = 10
某一个进程脏页达到整个内存10%时会立即回收,一个进程消耗了太多了
vm.dirty_background_bytes = 0
进程消耗脏页达到这个值就被回收
sync立即回收所有脏页
查看回收内存
[root@servera ~]# watch -n 1 'cat /proc/meminfo | grep Dirty'
Dirty: 0 kB
写随机数到磁盘 以此测试
[root@servera ~]# dd if=/dev/urandom of=/dev/vdc
Dirty: 14400 kB
达到14000左右就会被回收
[root@servera ~]# free -m
total used free shared buff/cache available
Mem: 1829 182 1459 16 187 1487
Swap: 0 0 0
因为到达了进程内存限制 10% (free+buff/cache)
提高比率
[root@servera ~]# sysctl -a | grep dirty
vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 40
vm.dirty_writeback_centisecs = 500
vm.dirtytime_expire_seconds = 43200
[root@servera ~]#
[root@servera ~]# tail -n 2 /etc/sysctl.conf
vm.dirty_background_ratio = 20
[root@servera ~]# sysctl -p
vm.dirty_background_ratio = 20
那么脏页会达到30000左右
打开swap
[root@servera ~]# free -m
total used free shared buff/cache available
Mem: 1829 188 1412 16 227 1479
Swap: 5119 0 5119
发现,就算开了swap他依然直到30000
那么跟swap是没有关系的
关闭进程限制,以查看整体脏页限制
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 40
谁先到谁回收
超过30秒回收
到达总体40%回收
注意
[root@servera ~]# sysctl vm.dirty_background_ratio=0
vm.dirty_background_ratio = 0
设置为0就不太好,没到多少就回收
根本不聚合
默认10%
你希望某一个应用程序得到io聚合,比如数据库,你希望它得到更多的聚合,你就设置
dirty_background_ratio多一点
系统整体不需要太低或太高就行
不回收数据有可能会丢,回收太快就没有聚合
pdflush
[root@servera ~]# sysctl vm.drop_caches=3
vm.drop_caches = 3
[root@servera ~]# cat /proc/sys/vm/drop_caches
3
[root@servera ~]#
我们其实不需要手动清空缓存
系统会自己清空缓存,一旦内存紧张
更倾向清空它,还是使用swap
当读取随机IO较多时,建议保留cache
否则,建议清空cache
[root@servera ~]# sysctl -a | grep swapp
vm.swappiness = 15
这个默认60
取值范围0-100
当内存紧张时
设置为0则尽量不使用swap,去释放内存得到更多资源,如果这个数字越大,越倾向于使用swap资源,而保留cache
tail -n 2 /etc/sysctl.conf
vm.swappiness = 5
当为5时
total used free shared buff/cache available
Mem: 1829 196 1173 16 458 1470
Swap: 5119 0 5119
[root@servera tuned]# bigmem 1100M
申请内存
total used free shared buff/cache available
Mem: 1829 1305 75 16 447 361
Swap: 5119 0 5119
他并没有使用swap,而是选择放弃缓存
内存不紧张你没必要释放cache,因为可以提高读性能。就算内存满了,他也会自动释放
你只有1800
你非要,要2000的内存
swap可也临时给你顶上,不然你的程序直接死机
total used free shared buff/cache available
Mem: 1829 1710 73 0 45 23
Swap: 5119 504 4615
我结束了bigmem,为什么swap还剩93
Swap: 5119 95 5024
当内存紧张时,内存中不用的数据暂时丢到swap中去。进程结束了,那个swap里的缓存数据不大且用不到。就还没被换到内存里来,还待在swap里
页中断,把数据都放到内存中,可以防止页中断。
minflt
主页中断 来自swap的内存,会影响性能
majflt
次页中断 不怎么影响性能
你分内存80%的内存来自swap性能变差
页切换