Linux内存拾遗

管理内存是操作系统的核心职责之一。Linux系统把内存分页管理,每一页(page)的大小可以用命令getconf PAGESIZE查看,单位是字节(Byte),Linux默认的页大小为4KB。


[root@localhost ~]# getconf PAGESIZE

4096

内存的总体情况可以通过cat /proc/meminfo查看


[root@localhost ~]# cat /proc/meminfo

MemTotal:       65751096 kB

MemFree:        64077144 kB

MemAvailable:   64061216 kB

Buffers:              2076 kB

Cached:           404000 kB

SwapCached:              0 kB

Active:           759688 kB

Inactive:         177952 kB

Active(anon):     532748 kB

Inactive(anon):    17212 kB

Active(file):     226940 kB

Inactive(file):   160740 kB

Unevictable:           0 kB

Mlocked:                 0 kB

SwapTotal:      33554428 kB

SwapFree:       33554428 kB

Dirty:                 8 kB

Writeback:               0 kB

AnonPages:        531796 kB

Mapped:            54212 kB

Shmem:             18396 kB

Slab:             194488 kB

SReclaimable:      72256 kB

SUnreclaim:       122232 kB

KernelStack:       13360 kB

PageTables:        12020 kB

NFS_Unstable:          0 kB

Bounce:                0 kB

WritebackTmp:          0 kB

CommitLimit:    66429976 kB

Committed_AS:    2371680 kB

VmallocTotal:   34359738367 kB

VmallocUsed:      415224 kB

VmallocChunk:   34308620284 kB

HardwareCorrupted:     0 kB

AnonHugePages:    290816 kB

HugePages_Total:       0

HugePages_Free:        0

HugePages_Rsvd:        0

HugePages_Surp:        0

Hugepagesize:       2048 kB

DirectMap4k:      217920 kB

DirectMap2M:     8124416 kB

DirectMap1G:    60817408 kB

本文主要总结一下在运维实践中遇到的跟内存有关的问题或技巧。

buffer cache和swap

free是系统管理员查看服务器内存情况常用的命令,在CentOS7.4上输出内容如下:


[[email protected] ~]# free

total        used        free      shared    buff/cache   available

Mem:         65751096     1079756    64070284         18396      601056    64054484

Swap:        33554428           0    33554428

从CentOS7系列版本开始,buffer和cache被合并为一列显示了,在之前的版本中是分开的。虽然被合并显示,但是它们保存的内容是不同的。

l  Buffer——顾名思义是缓冲区的意思,由于内存访问速度远超硬盘等块设备,所以Linux系统把文件系统中访问过的元数据缓存在buffer中,以提高下次访问的速度。

l  Cache——cache是缓存区,在内存足够的情况下,Linux系统总是倾向于把打开过的程序、文件内容缓存在内存中,所以长时间运行的服务器cache都比较大,这么做是为了下次访问这些文件更快。当有程序申请内存且空闲内存不足时,系统会释放cache以腾出空间。

l  Swap——在以前内存还是很金贵的资源时,为了“扩展”服务器有限的内存,Linux允许在块设备上划分出一块空间,将内存中不经常被访问的页置换到这里,腾出内存给处于活跃状态的进程,这个空间就是交换分区swap。由于硬盘比内存访问性能低,所以使用swap分区会降低性能。现在的服务器有一两百GB内存已经不稀奇了,似乎swap已经没有存在的意义了,其实不然,即使swap现在已经很少被用到了,我们在部署服务器时仍应该分配一个合理的空间给swap,有swap分区作为缓冲,可以避免系统因内存不足开始自动kill进程引起宕机,给运维人员处理内存饱和的问题争取时间,性能损失总比宕机要好。

实际情况中,有时会遇到有的服务器内存被cache占用完,系统开始把部分内存置换到swap中,导致性能急剧下降。这种情况下可以清理cache,释放出内存给进程用。清理cache的过程如下:


[root@localhost ~]# sync

[root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches

为了安全,清理cache前要先执行sync,使内存中的dirty数据落盘。

drop_caches取值范围为1,2,3,

1表示清理页面缓存;

2表示清理页面缓存和目录缓存;

3表示清理页面缓存、目录缓存和inode缓存。

为了减小系统使用swap分区的倾向,还有个内核参数可以调整——swappiness。swappiness的取值范围是0到100,数值越大系统使用swap分区的倾向就越大,为0时表示完全不使用swap。鉴于上面介绍过swap分区存在的必要性,我们不应该把swappiness设置为0,而应该设置为1,让系统尽可能避免使用swap分区,同时并不完全放弃使用swap的可能。


[root@localhost ~]# echo "vm.swappiness = 1" >> /proc/sys/vm/swappiness

[root@localhost ~]# sysctl -p

vm.swappiness   = 1

KSM

KSM(Kernel SamePage Merging)是一种压缩内存的技术,顾名思义就是将内存中内容相同的页进行合并以节省内存空间,当有进程需要修改该内存页的内容时,再将其拷贝一份再修改,也就是“写时复制copy on write”。KSM最早是为了优化qemu-kvm宿主机内存使用而诞生的,当一台宿主机上运行多个相同操作系统的虚拟机时,有很多内存页内容相同可以合并。KSM在CentOS6和CentOS7上是默认打开的,有两个相关服务:

l  ksm

l  Ksmtuned

ksmtuned依赖ksm服务,它的主体/usr/sbin/ksmtuned是一个shell脚本,通过读取配置文件/etc/ksmtuned.conf中的参数,对ksm的行为进行控制。在ksmtuned的控制下,ksm并不是一直在工作,它只在参数限定的条件达到的情况下工作,ksm是否在工作可以通过cat /sys/kernel/mm/ksm/run命令查看,0表示ksm没有在工作,1表示ksm在工作。

通过分析/usr/sbin/ksmtuned,可以了解配置文件中几个主要参数的含义:

l  KSM_MONITOR_INTERVAL=60 默认值为60,单位秒,表示每隔60秒,ksmtuned工作一次,扫描系统内存使用情况并据此调整ksm参数。数值越小ksmtuned工作频率越高,对cpu消耗越多;

l  KSM_SLEEP_MSEC=10 默认值为10,最小值也为10,单位毫秒,ksm扫描内存页的间隔,数值越小ksm扫描内存页的频率越高,对cpu消耗越多。对应的内核参数是/sys/kernel/mm/ksm/sleep_millisecs;

l  KSM_NPAGES_BOOST=300

KSM_NPAGES_DECAY=-50

KSM_NPAGES_MIN=64

KSM_NPAGES_MAX=1250

这一组参数用于设置ksm一次扫描多少内存页,对应内核参数/sys/kernel/mm/ksm/pages_to_scan。pages_to_scan的值在KSM_NPAGES_MIN和KSM_NPAGES_MAX之间波动,如果空闲内存大于临界值,需要降低ksm工作强度,则每次ksmtuned工作都会调低pages_to_scan 300(KSM_NPAGES_BOOST)页;反之,需要增强ksm工作强度,则每次ksmtuned工作会调高pages_to_scan 50(KSM_NPAGES_DECAY)页。

l  KSM_THRES_COEF=20

KSM_THRES_CONST=2048

这两个参数用于设置一个内存临界值,总内存的20%(KSM_THRES_COEF)和2048MB(KSM_THRES_CONST)两者之间取大者。当“所有qemu进程的内存”和临界值之和小于“总内存”,并且空闲内存大于临界值时,ksm停止工作,/sys/kernel/mm/ksm/run被置0;其他情况下,ksm处于工作状态,/sys/kernel/mm/ksm/run被置1。如果想让ksm早点开始工作,可以调高临界值。

常见的ksmtuned.conf配置如下:


# Configuration file for ksmtuned.

# How long ksmtuned should sleep between tuning   adjustments

KSM_MONITOR_INTERVAL=60

# Millisecond sleep between ksm scans for 16Gb server.

# Smaller servers sleep more, bigger sleep less.

KSM_SLEEP_MSEC=10

KSM_NPAGES_BOOST=300

KSM_NPAGES_DECAY=-50

KSM_NPAGES_MIN=64

KSM_NPAGES_MAX=1250

KSM_THRES_COEF=20

KSM_THRES_CONST=2048

# uncomment the following if you want ksmtuned debug   info

LOGFILE=/var/log/ksmtuned

DEBUG=1

日志/var/log/ksmtuned记录了ksmtuned每次执行的结果:


[[email protected] ~]# tail -100f   /var/log/ksmtuned

Thu Jan 18 11:29:18 CST 2018: total   65751096

Thu Jan 18 11:29:18 CST 2018: sleep 10

Thu Jan 18 11:29:18 CST 2018: thres   13150219

Thu Jan 18 11:30:18 CST 2018: committed 0   free 64470428

Thu Jan 18 11:30:18 CST 2018: 13150219   < 65751096 and free > 13150219, stop ksm

我的测试机内存比较空闲,ksm一直处于stop状态,下面我把KSM_THRES_COEF调大到100然后systemctl restart ksmtuned,强行让ksm工作,然后看看效果:


[root@localhost ~]# cat /sys/kernel/mm/ksm/run

1

[root@localhost ~]# tail -10f /var/log/ksmtuned

Thu Jan 18 15:05:05 CST 2018: sleep 10

Thu Jan 18 15:05:05 CST 2018: thres 65751096

Thu Jan 18 15:06:05 CST 2018: committed 0 free 64467712

Thu Jan 18 15:06:05 CST 2018: 65751096 > 65751096, start ksm

Thu Jan 18 15:06:05 CST 2018: 64467712 < 65751096, boost

Thu Jan 18 15:06:05 CST 2018: KSMCTL start 300 10

Thu Jan 18 15:07:05 CST 2018: committed 0 free 64468624

Thu Jan 18 15:07:05 CST 2018: 65751096 > 65751096, start ksm

Thu Jan 18 15:07:05 CST 2018: 64468624 < 65751096, boost

Thu   Jan 18 15:07:05 CST 2018: KSMCTL start 600 10

/sys/kernel/mm/ksm/pages_sharing记录了有多少内存页正在使用被合并的内存页,也就是实际节省的内存页数。页数乘以PAGESIZE就可以计算出实际节省的内存,命令如下:


echo$(($(cat   /sys/kernel/mm/ksm/pages_sharing)*$(getconf PAGESIZE)/1024/1024))MB”

NUMA

给有两路cpu的服务器插过内存的同学应该知道,每路cpu都有自己的内存条插槽。这是解决多cpu扩展问题的一种架构——NUMA,Non-Uniform Memory Access,非一致内存访问。为什么叫“非一致”呢?因为一个cpu访问自己的本地内存比访问别的cpu的内存速度要快,所以叫非一致。

numactl是一个管理numa的命令行工具,如果系统默认没有这个命令,可以通过yum install numactl安装。numactl –hardware可以查看cpu和内存的硬件情况,下面是一台4路服务器上执行命令的结果:


[root@localhost ~]# numactl --hardware

available: 4 nodes (0-3)

node 0 cpus: 0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60

node 0 size: 16338 MB

node 0 free: 15279 MB

node 1 cpus: 1 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61

node 1 size: 16384 MB

node 1 free: 15762 MB

node 2 cpus: 2 6 10 14 18 22 26 30 34 38 42 46 50 54 58 62

node 2 size: 16384 MB

node 2 free: 15646 MB

node 3 cpus: 3 7 11 15 19 23 27 31 35 39 43 47 51 55 59 63

node 3 size: 16384 MB

node 3 free: 15861 MB

node distances:

node   0   1   2   3

0:  10  20  30  20

1:  20  10  20  30

2:  30  20  10  20

3:  20  30  20  10

4路cpu就是4个numa nodes,每个nodes有16G的本地内存,整个服务器总共有64G物理内存。

numastat -c 可以查看指定进程的内存使用情况:


[root@localhost ~]# numastat -c nginx

Per-node process memory usage (in MBs)

PID              Node 0 Node 1 Node 2 Node 3 Total

-------------  ------ ------ ------ ------ -----

74675 (nginx)       0      0      1      0     1

74676 (nginx)       0      0      2      0     3

74677 (nginx)       1      0      1      0     3

74678 (nginx)       1      1      1      0     3

74679 (nginx)       0      0      2      0     3

74680 (nginx)       1      0      1      0     3

74681 (nginx)       0      1      1      0     3

74682 (nginx)       0      0      2      0     3

74683 (nginx)       1      0      1      0     3

74684 (nginx)       0      0      2      0     3

74685 (nginx)       0      1      1      0     3

74686 (nginx)       1      0      1      0     3

74687 (nginx)       0      0      2      0     3

74688 (nginx)       0      0      2      0     3

74689 (nginx)       0      1      1      0     3

74690 (nginx)       1      0      1      0     3

74691 (nginx)       0      0      2      0     3

74692 (nginx)       0      0      2      0     3

74693 (nginx)       0      1      1      0     3

74694 (nginx)       2      0      1      1     3

74695 (nginx)       0      0      2      0     3

74696 (nginx)       0      0      2      0     3

74697 (nginx)       1      1      1      0     3

74698 (nginx)       1      0      1      0     3

74699 (nginx)       0      0      2      0     3

-------------  ------ ------ ------ ------ -----

Total              18      6     35      5    65

上面的输出可以看出各个nginx进程的内存分散在了4个node上。

CentOS6和Centos7上都有一个叫numad的服务,这个服务负责在numa架构下调度各节点的内存分配,使内存分配具有cpu亲和性,例如一个线程运行在cpu0上,它申请的内存页将尽量从cpu0的本地内存中分配。这个服务默认没有开启,因为这种内存分配策略并不适合所有场景,当服务器上运行了很多应用程序或很多虚拟机时,numad具有cpu亲和性的内存分配方式可以提高性能,但是如果整个系统只运行一个高内存消耗的程序如数据库,numad反而会导致内存分配不均而降低性能,因此数据库服务器建议不要开启numad服务。

Linux系统中还有一个numa自动平衡策略,系统通过自动调配内存以求在各个numa nodes的内存使用率处于相对平衡的状态,这个策略可以通过修改内核参数/proc/sys/kernel/numa_balancing控制。关闭numa自动平衡策略:echo 0 > /proc/sys/kernel/numa_balancing;开启numa自动平衡策略:echo 1 > /proc/sys/kernel/numa_balancing。这个策略系统默认也没开启。

关于Linux内存的小技巧暂时只想到这么多,感谢阅读!

原文地址:http://blog.51cto.com/3646344/2096503

时间: 2024-10-06 22:45:07

Linux内存拾遗的相关文章

linux内存管理

一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程序可调用它.假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段.     2) 数据段:存放已初始化的全局变量.静态变量(包括全局和局部的).常量.static全局变量和static函数只能在当前文件中被调用.     3) 未初始化数据区(uninitializeddata s

Linux内存管理机制

一.首先大概了解一下计算机CPU.Cache.内存.硬盘之间的关系及区别. 1.  CPU也称为中央处理器(CPU,Central Processing Unit)是一块超大规模的集成电路, 是一台计算机的运算核心(Core)和控制核心( Control Unit).它的功能主要是解释计算机指令以及处理计算机软件中的数据.中央处理器主要由三核心部件组成,运算器.控制器和总线(BUS),运算器又主要由算术逻辑单元(ALU)和寄存器(RS)组成. 2.Cache即高速缓冲存储器,是位于CPU与主内存

Linux内存机制以及手动释放swap和内存

哇,感觉好久没更新了,今天我们来谈谈Linux的内存机制. 首先我们理一下概念 一.什么是linux的内存机制? 我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念. 物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换

Linux内存管理 【转】

转自:http://blog.chinaunix.net/uid-25909619-id-4491368.html Linux内存管理 摘要:本章首先以应用程序开发者的角度审视Linux的进程内存管理,在此基础上逐步深入到内核中讨论系统物理内存管理和内核内存的使用方法.力求从外到内.水到渠成地引导网友分析Linux的内存管理与使用.在本章最后,我们给出一个内存映射的实例,帮助网友们理解内核内存管理与用户内存管理之间的关系,希望大家最终能驾驭Linux内存管理. 前言 内存管理一向是所有操作系统书

攻城狮在路上(叁)Linux(二十五)--- linux内存交换空间(swap)的构建

swap的功能是应付物理内存不足的状况,用硬盘来暂时放置内存中的信息. 对于一般主机,物理内存都差不多够用,所以也就不会用到swap,但是对于服务器而言,当遇到大量网络请求时或许就会用到. 当swap被使用的时候,主机的硬盘灯就会闪烁不停. 本篇介绍两种方式:1.设置一个swap分区   2.创建一个虚拟内存的文件. 一.使用物理分区构建swap: 1.首先是分区: A.fdisk /dev/sda; <== 根据后续提示创建一个分区. B.修改分区的ID,因为fdisk默认将分区的ID作为文件

linux内存管理浅析

[地址映射](图:左中)linux内核使用页式内存管理,应用程序给出的内存地址是虚拟地址,它需要经过若干级页表一级一级的变换,才变成真正的物理地址.想一下,地址映射还是一件很恐怖的事情.当访问一个由虚拟地址表示的内存空间时,需要先经过若干次的内存访问,得到每一级页表中用于转换的页表项(页表是存放在内存里面的),才能完成映射.也就是说,要实现一次内存访问,实际上内存被访问了N+1次(N=页表级数),并且还需要做N次加法运算.所以,地址映射必须要有硬件支持,mmu(内存管理单元)就是这个硬件.并且需

启动期间的内存管理之初始化过程概述----Linux内存管理(九)

日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDrivers Linux内存管理 在内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换到保护模式, 然后内核才能检测到可用内存和寄存器. 而我们今天要讲的boot阶段就是系统初始化阶段使用的内存分配器. 1 前景回顾 1.1

linux内存源码分析 - 内存压缩(同步关系)

本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 概述 最近在看内存回收,内存回收在进行同步的一些情况非常复杂,然后就想,不会内存压缩的页面迁移过程中的同步关系也那么复杂吧,带着好奇心就把页面迁移的源码都大致看了一遍,还好,不复杂,也容易理解,这里我们就说说在页面迁移过程中是如何进行同步的.不过首先可能没看过的朋友需要先看看linux内存源码分析 - 内存压缩(一),因为会涉及里面的一些知识. 其实一句话可以概括页面迁移时是如何进行同步的,就是:我要开始对这

手工释放linux内存

当在Linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作为caching.这个问题,貌似有不少人在问,不过都没有看到有什么很好解决的办法.那么我来谈谈这个问题.一.通常情况先来说说free命令:引用[[email protected] ~]# free -m         total used free shared buffers cachedMem: 249 163     86      0        10           94-/+ b