2018-12-05 16:40:10 github_33719169 阅读数 272

Linux内存不足,添加swap分区

swap分区属于交换分区,起虚拟内存的作用。由于内存资源的宝贵,于是将硬盘的一部分作为内存来使用。所以在内存不足的时候,就可以通过适当的增加交换分区大小来达到增加内存的作用。

在编译mysql5.7.23的时候,购买的服务器内存只有1G,没有分配swap分区。最后在make的时候报错。网上查阅是内存不足的原因。

c++: internal compiler error: Killed (program cc1plus) Please submit a 
bug report, with preprocessed source if appropriate. See
<http://bugzilla.redhat.com/bugzilla> for instructions. make[2]: ***
[sql/CMakeFiles/sql.dir/item_geofunc.cc.o] Error 4 ma

解决方案

临时添加交换分区。

#创建1000M的分区文件
dd dd if=/dev/zero of=/swapfile bs=1024K count=1000
#创建swap分区文件
mkswap /swapfile
#挂载为swap分区
swapon /swapfile
#卸载之前挂载的swap分区
swapoff /swapfile

#查看内存状态
free -m
2019-08-21 18:34:12 ketaobaobao 阅读数 327

在Linux系统中,每个进程都独有一个虚拟地址空间(Virtual Address Space),由内核维护内存映射。为完成内存映射(虚拟内存地址映射到物理内存地址),内核为每一个进程维护一张页表。而页表存储在CPU的内存管理单元MMU中(即通过硬件完成了内存地址的查找)。

缺页异常

当进程访问的虚拟地址在页表中找不到时,就会产生缺页异常。此时会陷入内核空间完成物理内存分配、更新进程页表,然后恢复进程运行。

MMU以页为单位来管理内存,每个页通常为4KB大小,所以每一次内存映射需要关联4KB的整数倍的内存空间。

为了解决页表项过大问题,Linux提供多级页表(实际上是四级页表)和大页(HugePage)机制。

Linux虚拟地址空间分布

Linux的虚拟地址空间,大大增加了进程的寻址空间,32位系统的虚拟地址空间分布如图:

vas.gif

  • 只读段:只读,不可写;包括代码段、常量
  • 读/写段(或数据段):保存全局变量、动态变量
  • 堆:即平时说的动态内存,自下往上增长;堆内存由应用程序自己分配管理,依靠应用程序进行释放,但内核可将不常用数据换出到swap。大于128K的内存通过malloc()函数来分配(使用unmap()来释放),堆顶位置小于128K的内存通过brk()来分配(使用free()来释放)。
  • 文件映射区域:动态库、共享内存等映射物理空间的内存,自上往下增长;一般为mmap()函数所分配的虚拟地址空间
  • 栈:用于维护函数调用的上下文空间,一般为8M,ulimit -s查看
  • 内核虚拟空间:内核管理,对用户代码不可见。内核空间与用户空间的边界由TASK_SIZE控制。

对于64为Linux,内核空间占据顶部128T的虚拟地址空间,用户空间占据底部128T的虚拟地址空间。中间部分是未定义的。

另一张Linux虚拟地址空间分布图:

270929306664122.jpg

Linux内存回收

通过Linux虚拟地址空间分布,我们可以看出,Linux内存回收主要针对堆和文件映射区域。

  • 文件页:cache、buffer,通过内存映射的文件映射页
  • 匿名页:堆内存
  • 目录缓存和inode缓存

Linux内存回收时机

Linux提供2种内存回收时机:

  • 直接内存回收
  • 内核线程回收

直接内存回收

当发生内存分配,而此时的剩余空闲内存不足时,会执行立即内存回收。

内核线程回收

内核线程kswapd会定期扫描内存使用量,当剩余内存小于pages_free_low的值时,会进行内存回收,并确保可用内存高于pages_free_high。可通过修改/proc/sys/vm/min_free_kbytes文件的值来修改pages_free_min的值,另外两个值会自动计算得出。

kswapd0.png
NUMA架构中,每一个NUMA节点都会有一个kswapd线程。可通过numactl --hardware命令查看NUMA节点信息。

# cat /proc/sys/vm/min_free_kbytes
90112
# numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 20 21 22 23 24 25 26 27 28 29
node 0 size: 32642 MB
node 0 free: 188 MB
node 1 cpus: 10 11 12 13 14 15 16 17 18 19 30 31 32 33 34 35 36 37 38 39
node 1 size: 32768 MB
node 1 free: 68 MB
node distances:
node   0   1 
  0:  10  21 
  1:  21  10

Linux内存回收手段

Linux通过以下方式进行内存回收:

  1. 通过LRU算法回收文件页缓存:包括cache、buffer,通过内存映射的文件映射页;对于干净缓存直接回收、脏页回写到磁盘进行回收
  2. 程序不常访问的匿名页:通过swap机制回收堆内存
  3. OOM杀死oom_score大的程序:内存占用越大,oom_score越大,越容易被OOM;cpu占用越多,oom_score越小,越不容易被OOM;可通过/proc/$PID/oom_adj来影响oom_score的值,取值范围[-17, 15]
  4. 手动回收:通过修改/proc/sys/vm/drop_caches的值进行手动回收,最好再执行下sync命令回写脏页
    • 0:释放pagecache(即文件页)
    • 1:释放目录缓存和inodes
    • 3:释放pagecache(即文件页)、目录缓存和inodes

swappiness内存回收倾向

通过修改/proc/sys/vm/swappiness文件的值,使系统更倾向于回收匿名页或文件页,取值范围[0, 100]。
数值越大,越倾向于回收匿名页,越积极使用swap;
数值越小,越倾向于回收文件页,越消极使用swap;
但即使设置为0,仍然会使用swap。

NUMA

NUMA架构中,多处理器被划分到不同Node上,而同一个Node又进一步被换分为不同的内存域(Zone)。
在Linux中,默认开启NUMA,在我的系统(rhel6.5)上,64G的内存被划分为2个Node

# yum install -y numactl
# numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 2 4 6 8 10 12 14
node 0 size: 32757 MB
node 0 free: 237 MB
node 1 cpus: 1 3 5 7 9 11 13 15
node 1 size: 32767 MB
node 1 free: 137 MB
node distances:
node   0   1 
  0:  10  20 
  1:  20  10

当某node内存不足时,系统可以选择从其他node寻找空间内存,也可以选择从本node回收内存。具体偏好可以通过/proc/sys/vm/zone_reclaim_mode文件来控制。

  • 0:同时回收其他node和本node内存
  • 1:回收本node内存
  • 2:写脏数据回收本node内存
  • 4:匿名页回收本node内存

关闭NUMA

可以通过修改内核启动参数来禁用MUNA。

vi /boot/grub/grub.conf
...
kernel /boot/vmlinuz-2.6.18-128.1.16.0.1.el5 root=LABEL=DBSYS ro bootarea=dbsys rhgb quiet console=ttyS0,115200n8 console=tty1 crashkernel=128M@16M numa=off
...

swap查看

可通过cat /proc/$PID/status | grep VmSwap查看进程使用的swap情况。

也可通过smem命令查看进程使用的swap量。

查看swap使用最大的前10个进程:

# smem --sort swap -r | head -10
  PID User     Command                         Swap      USS      PSS      RSS 
12076 999      mysqld                        446756    60560    60894    61232 
22757 mysql    /usr/sbin/mysqld               61236     4360     4471     5520 
11864 root     /usr/bin/dockerd -H fd:// -    24848    16212    16212    16216 
  588 root     /usr/bin/containerd            13064     9688     9688     9692 
  590 root     /usr/bin/python3 /usr/share     7996        8        8       12 
  515 root     /usr/bin/python3 /usr/bin/n     7840        4        4        8 
12225 root     php-fpm: master process (/u     5988       52       71      116 
 4305 root     -bash                           3644     1852     2030     3196 
12368 www-data php-fpm: pool ww                3076     4668     6913     9184

查看每个用户的使用率

# smem -u
User     Count     Swap      USS      PSS      RSS 
nagios       1        0      704      728     1500 
chrony       1        0      700      885     2040 
dbus         1        0      892     1123     2508 
nobody      16        0     8832     9712    34300 
polkitd      1        0    11236    12009    14352 
root        28        0   194864   218192   269140

查看某进程(正则表达式匹配进程名):

# smem -P nginx
  PID User     Command                         Swap      USS      PSS      RSS 
 1423 root     nginx: master process /usr/        0      152      186     1160 
 1425 nobody   nginx: worker process              0      552      607     2144 
 1426 nobody   nginx: worker process              0      552      607     2144 
 1427 nobody   nginx: worker process              0      552      607     2144 
 1428 nobody   nginx: worker process              0      552      607     2144 
 1429 nobody   nginx: worker process              0      552      607     2144 
 1430 nobody   nginx: worker process              0      552      607     2144 
 1431 nobody   nginx: worker process              0      552      607     2144 
 1434 nobody   nginx: worker process              0      552      607     2144 
 1435 nobody   nginx: worker process              0      552      607     2144 
 1436 nobody   nginx: worker process              0      552      607     2144 
 1437 nobody   nginx: worker process              0      552      607     2144 
 1438 nobody   nginx: worker process              0      552      607     2144 
 1439 nobody   nginx: worker process              0      552      607     2144 
 1440 nobody   nginx: worker process              0      552      607     2144 
 1441 nobody   nginx: worker process              0      552      607     2144 
 1442 nobody   nginx: worker process              0      552      607     2140 
 9278 root     python /usr/bin/smem -P ngi        0     4628     5319     6820

nocache软件包

nocache软件包提供cachestatscachedel命令行工具,可查看、清理某文件在内存中的缓存。
bcc软件包中也提供一个cachestats命令行工具,可提供整个操作系统缓存的读写命中情况,另外还包含cachetop来提供每个进程的缓存命中情况。安装bcc软件包可能需要升级内核至4.1。

root@blog:~# cachestats /root/holiday.py 
pages in cache: 0/1 (0.0%)  [filesize=2.4K, pagesize=4K]
root@blog:~# cat /root/holiday.py &> /dev/null
root@blog:~# cachestats /root/holiday.py 
pages in cache: 1/1 (100.0%)  [filesize=2.4K, pagesize=4K]
root@blog:~# cachedel /root/holiday.py
root@blog:~# cachestats /root/holiday.py 
pages in cache: 0/1 (0.0%)  [filesize=2.4K, pagesize=4K]

/proc/sys/vm目录

/proc/sys/vm目录包含内存管理调优、buffer、cache管理的文件,这些参数用来调整Virtual Memory子系统的行为以及数据的写出(从RAM到ROM),具体如下。

文件 默认值 含义
/proc/sys/vm/admin_reserve_kbytes 3%的free pages与8MB中较小的值 系统中为拥有cap_sys_admin的权限(可以大致理解到root权限)的user预留的free memory数量。增大该值以保证root可登录并恢复系统。该值的修改需要考虑root登录后使用的工具(ssh、bash、ps、top、netstat等),一般推荐VSS+RSS。
/proc/sys/vm/block_dump 0,禁用 是否打开Block Debug模式,用于记录所有的读写及Dirty Block写回动作。
/proc/sys/vm/dirty_background_bytes 0 与dirty_background_ratio互斥,不可同时使用,设置了dirty_background_ratio之后,此项会变成0; 该文件定义脏数据的量,此时触发后台内核线程把脏数据写回磁盘
/proc/sys/vm/dirty_background_ratio 10 与dirty_background_bytes互斥,不可同时使用; 脏数据所占的页面,占包括free页面和可回收页面的在内的总可用页面数的百分比,此时触发后台内核线程将脏数据写回磁盘。这里说的总可用内存不等于系统的总内存。
/proc/sys/vm/dirty_expire_centisecs 3000(单位是1/100秒,即3s) 该文件表示如果脏数据在内存中驻留时间超过该值,后台内核线程会在下一次将把这些数据写回磁盘。
/proc/sys/vm/dirty_ratio 40 该文件表示如果进程产生的脏数据所占页面,占包括free页面和可回收页面的在内的总可用页面数的百分比,磁盘写操作的进程会自动把脏数据写回磁盘
/proc/sys/vm/dirty_writeback_centisecs 500(单位是1/100秒,即0.5s) 该文件表示后台内核线程周期性间隔多久把脏数据写回磁盘(即多少间隔唤醒一次)。
/proc/sys/vm/drop_caches 0 写入文件对应的值可使内核回收释放pagecache(即文件页,包括cache、buffer、通过内存映射的文件映射页)、目录缓存和inodes,从而得到更多空闲内存。 该操作是非破坏性的,脏数据不会被释放,应该在运行之前执行sync命令将所有缓存对象释放。 1:释放pagecache; 2:释放目录缓存和inodes; 3:释放pagecache、目录缓存和inodes;
/proc/sys/vm/hugetlb_shm_group 0 该文件表示允许使用hugetlb页创建System VIPC共享内存段的系统组ID。
/proc/sys/vm/legacy_va_layout 0 该文件表示是否使用最新的32位共享内存mmap()系统调用,Linux支持的共享内存分配方式包括mmap(),Posix,System VIPC。0,使用最新32位mmap()系统调用。1,使用2.4内核提供的系统调用。
/proc/sys/vm/min_free_kbytes 724(512M物理内存) 该文件表示强制Linux VM最低保留多少空闲内存(Kbytes)。
/proc/sys/vm/min_slab_ratio 5(%) 仅适用NUMA架构中; zone中可回收页面占总页面的百分比,超过后则进行回收; slab回收是基于每个zone/node的方式来触发的,这个过程可能不太快;
/proc/sys/vm/nr_hugepages 0 该文件表示系统保留的hugetlb页数。
/proc/sys/vm/nr_pdflush_threads 2(只读) 该文件表示当前正在运行的pdflush进程数量,在I/O负载高的情况下,内核会自动增加更多的pdflush进程。
/proc/sys/vm/overcommit_memory 0 该文件指定了内核针对内存分配的策略,其值可以是0、1、2。0,表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。1,表示内核允许分配所有的物理内存,而不管当前的内存状态如何。2,表示内核允许分配超过所有物理内存和交换空间总和的内存(参照overcommit_ratio)
/proc/sys/vm/overcommit_ratio 50(%) 该文件表示,如果overcommit_memory=2,可以过载内存的百分比,通过以下公式来计算系统整体可用内存。系统可分配内存=交换空间+物理内存*overcommit_ratio/100
/proc/sys/vm/page-cluster 3(2的3次方,8页) 该文件表示在写一次到swap区的时候写入的页面数量,0表示1页,1表示2页,2表示4页。
/proc/sys/vm/swapiness 60 该文件表示系统进行交换行为的程度,数值(0-100)越高,越可能发生磁盘交换。
/proc/sys/vm/vfs_cache_pressure 100 该文件表示内核回收用于directory和inode cache内存的倾向;缺省值100表示内核将根据pagecache和swapcache,把directory和inode cache保持在一个合理的百分比;降低该值低于100,将导致内核倾向于保留directory和inode cache;增加该值超过100,将导致内核倾向于回收directory和inode cache。

/proc/sys/vm中各文件含义大部分摘自:
https://www.cnblogs.com/xianbei/archive/2012/11/23/2783818.html

/proc/sys/vm中各文件含义部分内容参考:
https://blog.csdn.net/cassie_huang/article/details/80633328

smem命令:
https://linux.cn/article-4492-1.html

其他参考:

https://blog.csdn.net/weixin_33800593/article/details/90681825

https://cloud.tencent.com/developer/article/1004428

https://cloud.tencent.com/developer/article/1004429

2019-04-19 17:08:57 xiaosongluo 阅读数 46

1. Linux 中 swap 的作用

1.1 Linux 使用虚拟内存定义来简化应用使用内存的逻辑

在 Linux 中,内核使用虚拟内存技术,使每个应用程序均认为自己拥有独立且连续的可用的内存空间(一段连续完整的地址空间)。但是在实际上,实际内存空间通常使被映射到多个不同的物理内存段中,甚至还可能有部分内容暂时存储在外部磁盘存储器上,在需要时再加载到内存中来。

那么,实际的内存段存在多种类型,和swap相关的就有以下两种:

  • file backed:存储磁盘文件等形式的外部资源。第一次访问时由于找不到对应的物理内存,CPU会报 page fault 中断,然后操作系统就会处理这个中断并将文件的内容加载到物理内存中。一般程序的可执行文件,动态库用这种方式实现。
  • anonymous:存储程序自己用到的数据段和堆栈空间,逻辑上和 file backed 类似,只是当内存吃紧时,系统会直接删除掉file backed对应的物理内存,因为下次需要的时候还能从磁盘加载到内存,但anonymous page不能被删除,只能被swap out

1.2 交换空间(swap 空间)对Linux的意义

当 Linux 中的内存需要申请更多的内存时,但此时实际物理内存已经不足,那么,内核将会回收部分物理内存满足当前进程的需要,这样的回收主要依靠以下两种策略进行:

  • 对于 file backed 类型的资源,如果磁盘中有其完整备份(也就是没被修改过),所以内核可以直接释放掉对应的物理内存,当下次有进程需要访问这部分数据时,再由内核将它加载到内存中。
  • 对于 anonymous 类型的资源,这部分数据不能直接被删除,则由内核转移到提前在磁盘中申请的交换空间(swap 空间)中去,当下次有进程需要访问这部分数据时,再由内核将它加载到内存中。

因此,我们可以确定:

  1. 交换空间就是磁盘上预留的一块特殊空间,被系统用来临时存放内存中不常被访问的数据,可以降低内核对内存资源的依赖。
  2. 由于交换空间在磁盘上,所以访问速度要比内存慢很多,频繁的读写交换空间会带来性能问题

2. Linux 中使用 swap 的大致原理

2.1 水位线

内核中由三个watermark参数(WMARK_MIN、WMARK_LOW、WMARK_HIGH)来表示当前系统剩余内存的大致水平:

  • MEM>WMARK_HIGH:目前内存使用压力不大
  • WMARK_HIGH>MEM>WMARK_LOW:剩余内存存在一定压力
  • WMARK_LOW>MEM>WMARK_MIN:内存开始有较大压力,剩余内存不多了;
  • WMARK_MIN>MEM:内存面临很大压力,不过小于min这部分内存,内核是保留给特定情况下使用的,一般不会分配。

2.2 kswapd

kswapd 是系统的虚拟内存管理程序,内核会定期唤醒 kswapd:

  1. 如果此时 MEM>WMARK_HIGH ,kswapd则无需运行
  2. 如果此时 WMARK_HIGH>MEM,kswapd 进行内存回收
  3. 如果此时 WMARK_MIN>MEM,会触发内核直接回收操作(direct reclaim)

2.3 内存回收时,swap所占的比重

内存回收时,可以选择将 file backed 类型的资源直接释放掉,也可以选择将 anonymous 类型的资源进行 swap,这里就存在一个回收策略的问题,在 Linux 中可以通过 swappiness 参数进行策略调整:

  • swappiness=60(系统默认):对file backed的文件的释放比例会更大
  • swappiness=100:file backed 与 anonymous 将以同样的优先级进行回收
  • swappiness=0:尽量避免 swap, 但内存真的不够用时,还是会进行swap,比如 global_reclaim 的时候

2.4 Linux对 swap 的使用策略

  1. Linux 会倾向保持尽可能多的空闲物理内存,即使在内存压力不大的情况下,Linux 也会提前 swap 出暂时不用的内存,以应对的大内存压力做好准备
  2. 只有当被重新需要时,交换区的内容才会转移回物理内存

3 性能测试如何关注内存 swap 相关指标信息

3.1 整体策略

  1. 内存使用 swap 空间,是 Linux 正常的策略
  2. swap 空间用光时,系统就会发生错误
  3. 磁盘的读写速度很慢,因此频繁的 swap in / swap out(此时 kswapd CPU 使用率占比很高),说明内存已到瓶颈

3.2 指标及工具

工具:vmstat

[root@localhost ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 29607556 175112 2104620    0    0     0     0    7    3  0  0 100  0  0

内存饱和的现象:

  1. so 数值大
  2. swapd CPU使用率高

工具:free

[root@localhost ~]# free
              total        used        free      shared  buff/cache   available
Mem:       32739788      853792    29606080       19284     2279916    31418912
Swap:       6213628           0     6213628

内存饱和的现象:

  1. swap-used 占比大
2018-12-07 23:27:25 weixin_41950473 阅读数 7047

今天被叫着看一个性能问题,发现了一个很有意思的事情,当Linux的物理内存快被耗尽时,系统会把一些进程占用的内存转移swap区,当物理内存被释放一部分时,swap区的一些内存占用又慢慢回到mem区,但是mem区却不再是之前的满负荷状态,而是有一部分free的内存!

【17G大小进程压力测试结果】

  总资源消耗 内存类型 Used(G) Free(G) Total(G)
压力测试前 35.86 Mem 30.14 1.08 64
Swap 5.72 25.57
压力测试结束前期 34.78 Mem 12.78 18.45 64
Swap 22.00 9.30
压力测试结束后期 37.04 Mem 21.99 9.24 64
Swap 15.04 16.26

 

【总结】

  1. 当物理内存快被耗尽时,系统并没有崩溃,而是拿swap做临时内存,当两者都耗尽,系统OutofMemory
  2. 物理内存到达峰值,系统中可能一些不常用的进程内存占用被踢到swap区
  3. 当Mem区的资源进行释放时,被挪到swap的内存并不会全部回来的,随着系统或者程序的唤醒才会慢慢回到mem区
  4. Swap是内存不够时磁盘虚拟出来的内存,磁盘主要是I/O级别的操作并不是系统内核级别的操作,处理速度跟Mem区不是一个等级

 

 

2016-10-27 09:38:25 vbaspdelphi 阅读数 2032
  • 内存和swap图形
    这里写图片描述

  • 根据图片整理趋势对比

编号 mem变化趋势 swap变化趋势
1
2
3
4
5
6
7
8

* 趋势对比排列

编号 mem变化趋势 swap变化趋势
1
4
6
8
2
7
3
5

* 结论:
1. 内存使用无变化的时候,swap可能升也可能降
2. 内存使用上升的时候,swap有可能无变化,也有可能上升
3. 内存使用下降的时候,swap也会下降

备注:

  • 当前内存配置和使用情况
    这里写图片描述
    1. 当前swapniess是60,是不是说当内存使用了60%,也就是38GB之后,开始使用swap
    2. buffer和cache的使用确实不高,内存相当吃紧
    3. 内存的60%是38GB。

Linux内存中Swap机制

阅读数 2771

没有更多推荐了,返回首页