欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

马哥 49_02 _Linux内存子系统及常用调优参数 有大用

/node-admin/16258   如下图

只要硬件性能足够,任何关于cpu,内存等的性能的参数都不用调

硬件调优,就是选择硬件

如果是cache服务器,选什么样的硬件

如果是mysql服务器,选什么样的硬件

硬件本身在业务过程是I/O密集,还是cpu密集,对内存资源需要多少等等,针对这些有针对性的分析,有了这些直观认识,你才能知道我们当前这样一个服务,它应该运行在什么硬件上可能才更合适一点

,,,,,,,,,,,假如硬件条件已经设定了,跑在我们的硬件上的是操作系统,操作系统最核心的是内核,内核是整个硬件管理的最根本所在,所以如何能够有效的使用这些硬件,就是我们内核的功能,此前讲过,如何调整内存大小,如何调整进程的优先级,,,,,无非就是让我们的内核在使用计算资源上能够得到更有效的配置,,,,,,,以前讲的内存调优参数,无非就是加速我们内核在使用计算资源方面的能力,,,,,,,

再向上,真正向用户提供服务的就是我们的守护进程,每一种守护进程本身它的调整是各不相同的,,,,比如nginx应该怎么调??如果站在操作系统的层面来讲,nginx是一种网络服务,,,首先,它如何让我们的操作系统更好的响应nginx在网络方面的需求,其次,nginx运行起来以后,如何更有效的利用cpu资源,(cpu资源绑定,cpu隔离出来,专业为某一个nginx进程所用),,,,,,,,同时nginx如果各进程之间需要用到通信的话,那么内存当中进程间通信该如何调整,?????nginx自身如何调整?这就是nginx的参数了,使用多大的缓存,使用多少缓存,开启几个线程,,,,,,,这是我们又是通过观察你的系统性能上的某些参数指标来获取的,,,所以归根结底还是系统...


image.png



而对于某些特定服务来讲,它的参数调整在某些情况下,可能影响比较大,,,,,,,,,,,,,比如mysql这种比较复杂的服务,自身调整才是有意义的,比如我们的索引的设计,比如我们存储引擎的选择,存储引擎自身参数的调整,在服务级别,调整才有意义,,,,,,,,,,,,,而对于非常简单的服务来讲,服务级别调整意义并不大,就连apache服务器,无非也就是选择一个好的MPM模块,关掉某些不必要的功能,打开压缩机制,(压缩也未必是调优,它能够优化带宽的使用,但是会增加cpu的负荷),,,,所以没有放之四海而皆准的方法,最核心还是最基本的原理,,,,,,,,,,,

所以我们要观察系统性能的话,应该有哪些指标去衡量?内存使用,进程对cpu的使用,cpu的利用率,cpu队列?????,无非就是这些东西,还有我们的网络,网络缓冲区?是不是足够用,,,,,如果不够用的话,我们如何调整其大小,要不要通过网络各种参数的调整,比如说线程重用,进程重用,会话重用等来增加性能的,所以我们这里讲的内容就涉及到:第一,我们如何去观察这个性能指标(马哥以前讲了好多工具,去观察,去分析),,,,,第二,一旦发现某个指标不符合需要以后,(或者说通过观察之后,发现内存空间,交换空间),以内存为例,物理内存,交换内存,,物理内存没有使用完,但是它大量使用交换内存了,一旦出现这种情况,我们如何避免内存去使用交换内存,这样可以提高性能.


所以调优主要涉及三个层次,

1)硬件选型,

2)更核心的是系统内核自身的调优,(更重要的在于跟/proc,/sys目录打交道,调整工作参数的)

3)对于服务应用级别,无非也是服务如何使用系统资源,,,,,,对于服务自身来讲,有些参数确实可以调整,,,但一般来讲,只有复杂的服务,像oracle,mysql这样的数据库,通常我们才需要在某些特定的条件下进行调整,,而对于像web服务器这样的应用程序的调整,通常都很简单,通过观察一些性能指标,通过我们网络带宽的资源使用,我们就能分析出来我们应该在什么地方,对哪些参数进行调整,,,,,,,,,,,,,,还有无非也就是某些应用上,关闭DNS服务,避免一些不必要的功能,,,,,,,,,我们的核心着眼点,主要就在于底层1),2)这两个层次上


马哥说以后会讲mysql索引的优化以及mysql的各种参数,包括各种存储引擎的参数是如何使用系统资源的,以这个为例,来讲应用层调优,,



而事实上,对于我们整个操作系统而言,我们整个调优着眼点,是以下几个方面

1) 进程管理,无非是在cpu时间片的分片上如何实现

2) 内存调优,这是最复杂的,

3) I/O调优,如何优化我们对I/O的应用,尤其是磁盘I/O

4) 文件系统,当然文件系统本身与I/O仍然是有关系的,,,在磁盘I/O特定的条件下,不同文件系统的性能在某种业务上的表现可能有所不同,

5) 网络子系统调优,

通常而言,我们调优主要就是涉及到这几个层面,


调优思路,无非就是观察性能指标,看看谁是系统瓶颈,

1)如何获取性能指标,来观察我们系统的性能瓶颈所在,

2)根据我们自己观察的性能瓶颈,来确定一下我们应该调整哪些参数,,,,并不是一上来把每一个参数都调一调,更重要的是,有的时候,观察到是cpu利用率过高,但是可能最终发现,它压根不是cpu的问题,因为可能cpu被大量用来实施I/O上去了,所以cpu利用率还是过高,,,,,,,所以我们要综合多方位,多角度的去分析到底真正的性能瓶颈在什么地方,还得只能一个参数一个参数的调,调一个不行,再调一个,再再调一个,,而后两个两个的调,这个过程是非常麻烦的,,,,,,,,



所以红帽官方把系统调优称为 Black art (黑色艺术),调优很麻烦,官方现在出了个文档

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/index


Monitoring and Analyzing System Performance     #监控性能以及分析系统性能评估的工具

下面这四个工具都是做系统全方位性能评估的,用起来麻烦,马哥不打算讲涉及到它们的应用

SystemTap    #这个工具都要用到SystemTap编程的,工作3-4才有可能用到它,要了解这个工具的使用需要很久的,有点类似于strace,能够让我们观察系统上每一个系统调用,每一个应用程序在跟内核进行交互时的活动状态的,,,是让你观察系统各个模块的运作的方式的,运行细节的,,很难,马哥没空讲,讲了也听不懂

OProfile    #评估操作系统性能的一个非常重要的工具,,这个是作性能评估的,,很难,马哥没空讲,讲了也听不懂

Valgrind    #图标logo是唐吉呵德,中世纪的巴骑士,是纸折的,,是非常强大的内存泄漏探测工具,是程序员编完程序以后评估自己程序的内存泄漏,内存缓存的,对于缓存本身的使用率等评估工具,,,也是一个多方位的,能够实现多种功能的cpu缓存命中的评估工具,应用程序的内存泄漏的评估工具,应用程序对缓存的利用率的评估工具,,,,功能强大,讲清楚也要很久,,,,但是它的偶尔某个子命令的使用偶尔很有用,,,,,比如我们评测一下内存的使用情况,有没有内存泄漏,,,,简单使用一下,虽然很简单,但是无助于我们实现系统分析的

Perf    #红帽6上引入到红帽系统上的一个非常有用的工具,系统性能评估工具,也是一个性能参数评估优化工具;;;;相对简单一点

这四个工具都是在系统级别完成的,


从系统级别调优上,

CPU

    CPU and NUMA Topology

    numastat

    

    CPU Scheduling

    Interrupts and IRQ Tuning


Memory

    Huge Translation Lookaside Buffer (HugeTLB)

    Huge Pages and Transparent Huge Pages

    Using Valgrind to Profile Memory Usage    #使用Valgrind来评估内存用法

        Profiling Memory Usage with Memcheck

        Profiling Cache Usage with Cachegrind

        Profiling Heap and Stack Space with Massif

    Capacity Tuning   # Capacity 调优,无非就是怎么使用交换内存,什么时候启动 pdflush ????如何调整大内存页的个数等


     Input/Output

        Features

        Analysis    #性能分析

        Tools

        Configuration

        Completely Fair Queuing (CFQ)        #磁盘队列

        Deadline I/O Scheduler                     #最后期限队列????

        Noop                                                 #没有任何操作的调度器

    File Systems

        Tuning Considerations for File Systems

        Formatting Options

        Mount Options

        File system maintenance

        Application Considerations

        Profiles for file system performance

        File Systems

            The Ext4 File System        #Ext4 文件系统

            The XFS File System         #XFS 文件系统

        CIFS

        Clustering

            Global File System 2            #全局文件系统 2 

    Networking

        Network Performance Enhancements

        Optimized Network Settings

        Overview of Packet Reception

        Resolving Common Queuing/Frame Loss Issues

        NIC Hardware Buffer

        Socket Queue


马哥 讲的 次要部分 https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/index

里面的内容,主要部分是 rhca 当中专门实现操作系统调优的内容,是rh 442 那本书?????

马哥精简了那本书,放在一个ppt里面,没用的内容(比如软raid调优)就不讲了


进程管理,CPU;;难

内存调优;;难

I/O;;简单

文件系统;;简单

网络子系统;;简单




如何实现内存当中进程间通信相关内存的调优,

 进程间通信对linux而言,有三种常用的进程间通信机制,

messages(消息), semaphores(信号,与此前的signal信号不一样), and shared memory(共享内存)

调优就是对这三种机制所各自能够实现的容量大小; 

比如 messages , 最大可以启动多少个messages同时使用

比如 semaphores , 最大可以启动多少个semaphores 同时使用????

比如 shared memory , 最大可以使用多少内存??一个内存里面最多可以容纳多少个共享的信号???????

[root@localhost ~]# man ipc

IPC(2)                     Linux Programmer’s Manual                    IPC(2)


NAME

       ipc - System V IPC system calls


SYNOPSIS

       int ipc(unsigned int call, int first, int second, int third,

               void *ptr, long fifth);


DESCRIPTION

       ipc()  is  a  common  kernel entry point for the System V IPC calls for

       messages(消息), semaphores(信号), and shared memory(共享内存).   call  determines  which  IPC

       function  to  invoke;  the  other  arguments  are passed through to the

       appropriate call.


       User programs should call the  appropriate  functions  by  their  usual

       names.   Only  standard library implementors and kernel hackers need to

       know about ipc().


CONFORMING TO

       ipc() is Linux-specific, and should not be used in programs intended to

       be portable.


NOTES

       On  a  few  architectures,  for  example ia64, there is no ipc() system

       call; instead msgctl(2), semctl(2), shmctl(2), and  so  on  really  are

       implemented as separate system calls.


SEE ALSO

       msgctl(2),   msgget(2),  msgrcv(2),  msgsnd(2),  semctl(2),  semget(2),

       semop(2), semtimedop(2), shmat(2), shmctl(2), shmdt(2), shmget(2)

COLOPHON

       This page is part of release 3.22 of the Linux  man-pages  project.   A

       description  of  the project, and information about reporting bugs, can

       be found at http://www.kernel.org/doc/man-pages/.


Linux                             2007-06-28                            IPC(2)



[root@localhost ~]# ipcs -l        #看看当前的ipc的限定

#我们通常的调整,尤其是我们跟应用程序相关的,用的比较多的进程间通信,通常是Shared Memory Limits 和 Messages: Limits


------ Shared Memory Limits --------

max number of segments = 4096        #最大多少个段

max seg size (kbytes) = 67108864        #最大段大小

max total shared memory (kbytes) = 17179869184    #允许在全局范围内可以使用的共享内存是多大kbytes

min seg size (bytes) = 1        #最小段是多大,,,意味着一个信号???????至少要使用一个字节来传输的


------ Semaphore Limits --------        #现在很少对它进行调整了

max number of arrays = 128

max semaphores per array = 250

max semaphores system wide = 32000

max ops per semop call = 32

semaphore max value = 32767


------ Messages: Limits --------

max queues system wide = 3739    #如果基于信号来的话,message队列,全局系统范围内最大有多少个队列,

max size of message (bytes) = 65536    #每个信息的最大大小

default max size of queue (bytes) = 65536        #默认每个队列中的最大信息????所能够接受进来的最大消息的体积是多大????????


[root@localhost ~]#


[root@localhost ~]# man ipcs

IPCS(1)                    Linux Programmer’s Manual                   IPCS(1)


NAME

       ipcs - provide information on ipc facilities


SYNOPSIS

       ipcs [-asmq] [-tclup]

       ipcs [-smq] -i id

       ipcs -h


DESCRIPTION

       ipcs  provides  information on the ipc facilities for which the calling

       process has read access.


       The -i option allows a specific resource  id  to  be  specified.   Only

       information on this id will be printed.


       Resources may be specified as follows:


       -m     shared memory segments    # 单独显示 Shared Memory


       -q     message queues    #单独显示Messages


       -s     semaphore arrays    #单独显示Semaphore


       -a     all (this is the default)    #默认-a,显示三种Shared Memory Limits, Semaphore Limits,Messages: Limits


       The output format may be specified as follows:


       -t     time


       -p     pid         #以pid来进行显示的


       -c     creator    #显示某一个信号的创建者是谁?


       -l     limits    #显示 limits


       -u     summary


SEE ALSO

       ipcrm(1), ipcmk(1)


CONFORMING TO

       The  Linux ipcs utility is not fully compatible to the POSIX ipcs util-

       ity.  The Linux version does not support the -b  and  -o  options,  but

       does  support  the -l and -u options not defined by POSIX. The portable

       application shall not use the -a, -b, -o, -l, and -u options.


AUTHOR

       krishna balasubramanian (balasub@cis.ohio-state.edu)


AVAILABILITY

       The ipcs command is part of the util-linux-ng package and is  available

       from ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.


Linux 0.99                      9 October 1993                         IPCS(1)





[root@localhost ~]# ipcs -p        #指定pid????,这里没有指定,就是所有???? 它创建了哪些共享内存实现进程间通信的?创建了哪些 Message Queues完成进程间通信? 这里没有显示Semaphore,说明一般它不重要


------ Shared Memory Creator/Last-op --------

shmid      owner      cpid       lpid



------ Message Queues PIDs --------

msqid      owner      lspid      lrpid


[root@localhost ~]#


万一某个进程间通信睡眠了,而唤醒不了了,使用 rpcrm(ipcrm: ipc remove ( inter Process Communication  remove) 进程间通信移除)命令



[root@localhost ~]# man ipcrm

Cannot open the message catalog "man" for locale "zh_CN.UTF-8"

(NLSPATH="/usr/share/locale/%l/LC_MESSAGES/%N")


Formatting page, please wait...

IPCRM(1)                   Linux Programmer’s Manual                  IPCRM(1)


NAME

       ipcrm - remove a message queue, semaphore set or shared memory id

#移除一个消息队列,semaphore,shared memory 的id,,,如果某个消息队列处于睡眠状态,而且无法唤醒被使用,卡死了,可以使用 ipcrm 命令来删除,

SYNOPSIS

       ipcrm [ -M key | -m id | -Q key | -q id | -S key | -s id ] ...


       deprecated usage


       ipcrm {shm|msg|sem} id...



进程间通信管理命令:

    ipcs

    ipcrm


我们调整的进程通信的机制通常只关系到共享内存和messsages


如下图,

关于共享内存的

shmmni:  ( Specifies maximum number of shared memory IDs ) 在全系统范围内最大允许使用多少个共享内存段,,,,,,指定最大数目的共享内存段,,,,,,,,,,,,这是经常调的参数,尤其是在数据库服务器上,4096有时可能显得有点少,,,,,系统级别,所允许使用的共享内存段上限:

shmall: shared memory all pages number 最大页面数,,,,,,全局范围内一次性可以使用的最大共享内存页面数,,,,,,,,,系统级别,能够为共享内存分配使用的最大页面数   This should be at least kernel, shmmax/PAGE SIZE

shmmax: shared memory max 单个共享内存段的最大的大小上限,,,单位是字节之类的吗????,,,,,,


(

kernel.shmmni:全系统范围内最大允许多少个共享内存段,默认4096
数据库服务器调整居多
kernel.shamall:全局范围内能够使用的最大共享内存页面数,默认2097152
此值最小范围不能小于:kernel.shmmax/PAGE_SIZE
kernel.shmmax:单个共享内存段最大的上限值

)



image.png


如下图,

关于消息的,三个参数,这三个参数经常会被调整

msgmni: message max number of message queue idenfitifiers 系统范围内最多多少个消息队列,,系统级别,消息队列个数上限  默认16

msgmnb: message max number of bytes  in a single message ,单个消息队列的最大字节数,默认是16384

msgmax: shared memory max 进程间通信的时候所能够使用的消息的最大上限,单个消息大小的上限,单位是字节,,,,,(一个消息队列里面可能放了好多消息),,,默认8192


image.png



shm:

shmmni: 系统级别,所允许使用的共享内存段上限:

shmall: 系统级别,能够为共享内存分配使用的最大页面数:

shmmax: 单个共享内存段的上限:

messages:

msgmni: 系统级别,消息队列个数上限:

msgmnb: 单个消息队列的上限,单位为字节:

msgmax: 单个消息大小的上限,单位为字节:


以上的六个值都需要按需调整,,一般都需要将其调大的


我们可以通过 ipcs -p 等来查看某一个应用的共享内存大小,消息队列等等,一旦发现不够用了,将其调大就行了,调大多少,得自己慢慢测试


调整内存使用空间期限,

如下两图

调整 kswapd?????,,,,,尤其是pdflush,,,,,,,是如何清洗内存空间,(如何回收内存的),,,,,,,一旦内存不够用了,或者为了保证我们的数据应该尽可能的被持久保存, 就应该将数据不停地清洗到磁盘上去,,,,所在 pdflush线程就是用来完成这个工作的,,,内核里面应该启动多少全?????pdflush线程?

image.png


image.png



[root@localhost ~]# ps aux | grep pdf        #没有关于pdflush的线程,说明没启动,

root      2542  0.0  0.0 103336   872 pts/0    S+   14:40   0:00 grep pdf

[root@localhost ~]#


因为 pdflush 是按需启动的,它不会随时运行的,它是定期启动的,如果有磁盘需要刷写的话,可能会启动起来,否则不会启动


[root@localhost ~]# ps auxf         #没看到pdflush

image.png



我们应该启动多少个pdflush线程?pdflush就是用来倾写内存中的脏页到磁盘上去的,,,pdflush如果个数多的话,可以并行多个执行,


如下图

一般最少两个,应该是几个???一般来讲,它们会自动优化,一个I/O设备(不是一个分区,而是一块磁盘)一个,这是最繁忙的情况下我们应该调整的pdflush的个数,,,,,,,,,,,,,,可以自己去定义它,echo一个值到vm.nr_pdflush_threads里面就让它启动多少个(我 echo 一个值,提示权限不够,,,,,此时

cat /proc/sys/vm/nr_pdflush_threads  结果为 0个,是不是只有非0时(即有pdflush线程时)才可以修改)

vm.nr_pdflush_threads    #显示当前有多少个,用来显示当前默认定义了启动多少个pdflush内核线程


image.png



[root@localhost ~]# cat /proc/sys/vm/nr_pdflush_threads        # 0个,说明当前没启动pdflush

0

[root@localhost ~]#


如下图

红帽6上,它会自动去管理pdflush线程个数的,因此个数本身我们可以不用调,但是有几个参数我们需要调,

调pdflush工作属性的,,,,,,,,,,pdflush什么时候启动起来,启动起来如何进行工作,等等这几个内核参数至关重要,

下面两个是按比率进行评估的

1)vm.dirty_background_ratio    #相对于全部内存来讲,脏页占了多大的比例后,pdflush开始启动,进行倾写,,,这是系统级别的定义,,,,这是倾写预值,可以理解成触发条件,,,,,,全局范围的

2)vm.dirty_ratio    #相对于全部内存来讲,对于某一个单进程来讲,进程自己的脏页占了多大的比例后,开始启动倾写操作,,,,,,单个进程范围的,,,,,

可以看看  /node-admin/16258


下面两个是与时间控制有关的参数

3)vm.dirty_expire_centisecs    #centisecs是百分秒,如果dirty_background_ratio和dirty_ratio都没满足时,也要倾写的话,所以要定义时间间隔,,,每隔多长时间唤起一次,,,,,,0表示禁止,,,,,pdflush周期性启动倾写操作的时间间隔,单位为百分秒,,,,,,每隔多长时间清洗线程会自动启动起来一次

4)vm.dirty_writeback_centisecs   #这是一个观察期限,如果发现某一个脏页已经足够久了,这个脏页在内存里面已经存储很长时间了,它会起来把这个脏页刷写出去,,,,,它用于定义多长时间为脏页变为足够久的时间,而且需要启动起来要刷写至磁盘中的,单位依然是centisecs百分秒,,,,,,,,一个脏页(针对单个脏页来讲的)在内存中存储多久以后变为过期并且需要立即启动倾写线程,,,,观察某单个脏页或某些脏页只要足够老了, 就必须要将它们倾写到磁盘上去(启动清洗线程)






image.png


dirty_background_ratio,dirty_ratio 这两个参数很多时候都需要调   


[root@localhost ~]# cat /proc/sys/vm/dirty_background_ratio        #

10

[root@localhost ~]#

[root@localhost ~]# cat /proc/sys/vm/dirty_ratio        #不懂,为什么值更大呢??应该更小

20

[root@localhost ~]#

红帽5,红帽6 dirty_background_ratio,dirty_ratio       #这些值可能不一样的    


[root@localhost ~]# cat /proc/sys/vm/dirty_bytes    #我们可以定义达到多少字节的时候开始倾写,为0表示没定义,使用dirty_ratio , dirty_background_ratio 来控制 ,,,,事实上我们很少使用dirty_bytes    来控制

0

[root@localhost ~]#



pdflush是用来回收脏页的

如何回收干净的页面?释放缓存就可以了,


# sync 命令??????它是同步脏页脏缓存



如下图

sync命令本身主要功能是实现将脏页脏缓冲给它同步到硬盘上去的,,,,,,同步完就可以回收了,,,,,所以要先同步才能回收,,,,,,,,,,(同步完以后就变成干净的页了),,,,,,,


pdflush是系统自己自动启动的,是内核线程自动完成的

手动倾写脏缓冲和缓存(能够倾写所有的脏缓冲和页面到磁盘上去的命令)

        1) # sync 命令

        2) # echo s > /proc/sysrq-trigger    使用系统上的一个魔术控制符,这是系统级别的某个资源管理的触发器,它有很多参数可以用,也能完成倾写,倾写完成以后,就可以回收了


回收干净页的方法:  主要是向 /proc/sys/vm/drop_caches 文件中发送一个数值 (drop_caches 释放缓存)

0     #表示不释放

1 to free pagecache        #释放页面缓存 一般释放它,,,,,,,,,,,,,,dentries和inodes这两个最好不要释放,除非在极端场景下,因此我们通常 echo 1 >  /proc/sys/vm/drop_caches 

2 to free dentries  and inodes        #释放dentries和inodes    

3 to free pagecache, dentries and inodes        #释放pagecache,dentries和inodes     

image.png


[root@localhost ~]# free  -m        #看到 buffers,cached 占据了一些空间     

             total       used       free     shared    buffers     cached

Mem:          1872        249       1623          0         21         77

-/+ buffers/cache:        150       1722

Swap:         4031          0       4031

[root@localhost ~]#


[root@localhost ~]# sync        #先sync 同步脏页到磁盘

[root@localhost ~]#

[root@localhost ~]# echo 1 > /proc/sys/vm/drop_caches        #回收干净的缓存缓冲,,,,因为我们不释放dentries和inodes,所以cached中仍然会有些内容(是 slab cache allocate分配出去的,,,它分配出去的有时在buffer中,有时在cache中,,,,可能这里,红帽6系统上被归类为cache了)(只要执行了sync命令,buffer一般都会被同步到磁盘上的,所以buffer可以完全释放,但是cache一般无法完全释放)

[root@localhost ~]#

[root@localhost ~]# free -m            #buffers, cached足够小了    

             total       used       free     shared    buffers     cached

Mem:          1872        162       1709          0          0         12

-/+ buffers/cache:        150       1722

Swap:         4031          0       4031

[root@localhost ~]#

[root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches        #echo 3 也无法完全释放,因为无论如何,我们一定会打开一些文件的,马哥说我们容易理解

[root@localhost ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          1872        158       1714          0          0         12

-/+ buffers/cache:        145       1727

Swap:         4031          0       4031

[root@localhost ~]#


一旦我们的内存超限了,内存耗尽了,怎么办?内存耗尽了,内核会启动OOM killer,用于实现将那些非常消耗内存的进程给它杀死,以腾出内存空间的,,,

到底杀死哪些进程呢?

如下图

比较这个进程的oom_score,谁的高,,,,,,,,,oom_adj这个分数一般是 -17至15之间的一个值,数字越高,就越像坏蛋,就越优先被杀死,,,,,什么时候会启动oom-killer?在zone_normal区域中,没有可用的空闲空间时,就意味着内存耗尽了,(不光是 zone_highmem????? 32位系统上有 zone_highmem 这一段,这一段是超出1G以上范围的段 ),在zone_normal段中,只要内存耗尽,无论zone_highmem中有没有内容,它一段会启动oom killer的,(64位的系统中,都是作为zone_normal的,除了zone_dma,,所以在这各情况下,只有所有的内存都耗尽了),,,

image.png



如果允许内核在内存耗尽的时候使用 oom kill 的功能,我们都开放一个选项 /proc/sys/vm/panic_on_oom, 如果设定为0,则表示告诉内核,一旦内存耗尽了,就可以使用oom killer,


每个进程都有个分数评估,谁的分数大,就会被优先杀死,

[root@localhost ~]# ls /proc/1

attr        coredump_filter  io         mountstats     pagemap      stack

autogroup   cpuset           limits     net            personality  stat

auxv        cwd              loginuid   ns             root         statm

cgroup      environ          maps       numa_maps      sched        status

clear_refs  exe              mem        oom_adj        schedstat    syscall

cmdline     fd               mountinfo  oom_score(分数)      sessionid    task

comm        fdinfo           mounts     oom_score_adj  smaps        wchan

[root@localhost ~]#


oom_score 是系统观察进程自动计算得来的,而计算这个数值,主要参照于oom_adj, oom_adj 的值是从 -17到15(有效范围是从-16至15,,,若值为-17,则在任何情况下oom killer 都不会kill掉这个进程)(oom_adj的值-16至15,是用来判定计算得出当前进程oom_score值的一个基本标准,,,,,,,oom_adj的值越大,得到的oom_score值也就越大,被杀死的可能性也就越大)


oom_adj的值

-16至15:协助计算oom score

-17: disables the oom killer for that process. 禁用oom killer


oom killer 在有些场景下可能会带来意外结果,假如某一个服务非常重要,不能被kill掉,但是oom killer会kill掉它的,,,因此可以把这个服务的 oom_adj 的值设为-17,避免被kill掉


如下图


如果要禁用 oom kill 的功能

vm.panic_on_oom = 1 # 禁用

vm.panic_on_oom = 0 # 启用

oom_score的值是2的n次方(n就是oom_adj的值)

oom_score被称为 badness_score(坏蛋分数)image.png


如下图

如何使用valgrind来评估内存泄漏,

vargrind是一个有着很多子命令的命令

($$: 美元符美元符,两个美元符,取得当前进程的进程号)

# valgrind --tool=memcheck cat /proc/$$/maps        #是用来评估当前进程的内存使用状况

image.png


[root@localhost ~]# yum search valgrind            #valgrind命令的程序包的名字也叫valgrind 

已加载插件:product-id, search-disabled-repos, security, subscription-manager

This system is not registered with an entitlement server. You can use subscription-manager to register.

============================ N/S Matched: valgrind =============================

eclipse-valgrind.x86_64 : Valgrind Tools Integration for Eclipse

valgrind.i686 : Tool for finding memory management bugs in programs

valgrind.x86_64 : Tool for finding memory management bugs in programs


  Name and summary matches only, use "search all" for everything.

[root@localhost ~]#

[root@localhost ~]# yum whatprovides */valgrind          #valgrind命令的程序包的名字也叫valgrind

已加载插件:product-id, search-disabled-repos, security, subscription-manager

This system is not registered with an entitlement server. You can use subscription-manager to register.

eclipse-valgrind-0.6.1-1.el6.x86_64 : Valgrind Tools Integration for Eclipse

Repo        : cdrom

匹配来自于:

Filename    : /usr/lib64/eclipse/dropins/valgrind




1:valgrind-3.8.1-9.el6.i686 : Tool for finding memory management bugs in

                            : programs

Repo        : cdrom

匹配来自于:

Filename    : /usr/lib/valgrind

Filename    : /usr/bin/valgrind




1:valgrind-3.8.1-9.el6.x86_64 : Tool for finding memory management bugs in

                              : programs

Repo        : cdrom

匹配来自于:

Filename    : /usr/lib64/valgrind

Filename    : /usr/bin/valgrind




1:valgrind-3.8.1-9.el6.x86_64 : Tool for finding memory management bugs in

                              : programs

Repo        : installed

匹配来自于:

Filename    : /usr/bin/valgrind




[root@localhost ~]# yum install valgrind

已加载插件:product-id, search-disabled-repos, security, subscription-manager

This system is not registered with an entitlement server. You can use subscription-manager to register.

设置安装进程

包 1:valgrind-3.8.1-9.el6.x86_64 已安装并且是最新版本

无须任何处理

[root@localhost ~]# m

[root@localhost ~]# 


[root@localhost ~]# man valgrind            #valgrind有很多组件,各个组件的功能不一样,默认的组件是memcheck,,常见有的Memcheck, Cachegrind(评估缓存命中率的????),,,,我们常用的是Memcheck

Cannot open the message catalog "man" for locale "zh_CN.UTF-8"

(NLSPATH="/usr/share/locale/%l/LC_MESSAGES/%N")


Formatting page, please wait...

VALGRIND(1)                      Release 3.8.0                     VALGRIND(1)


NAME

       valgrind - a suite of tools for debugging and profiling programs

        #用来调试和profiling 应用程序的

SYNOPSIS

       valgrind [valgrind-options] [your-program] [your-program-options]


DESCRIPTION

       Valgrind is a flexible program for debugging and profiling Linux

       executables. It consists of a core, which provides a synthetic CPU in

       software, and a series of debugging and profiling tools. The

       architecture is modular, so that new tools can be created easily and

       without disturbing the existing structure.


       Some of the options described below work with all Valgrind tools, and

       some only work with a few or one. The section MEMCHECK OPTIONS and

       those below it describe tool-specific options.


       This manual page covers only basic usage and options. For more

       comprehensive information, please see the HTML documentation on your

       system: $INSTALL/share/doc/valgrind/html/index.html, or online:

       http://www.valgrind.org/docs/manual/index.html.


TOOL SELECTION OPTIONS

       The single most important option.


       --tool=<toolname> [default: memcheck]            # --tool指定子组件的名称

           Run the Valgrind tool called toolname, e.g. Memcheck, Cachegrind,

           etc.


BASIC OPTIONS




[root@localhost ~]# rpm -q valgrind        #检测这个软件是否已经装过

valgrind-3.8.1-9.el6.x86_64

[root@localhost ~]#


[root@localhost ~]# valgrind --tool=memcheck cat /proc/$$/maps

==3998== Memcheck, a memory error detector        #开始评估

==3998== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.

==3998== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info

==3998== Command: cat /proc/3059/maps

==3998==

#下面是每一个文件 的内容??????

00400000-004d5000 r-xp 00000000 fd:00 1708138                            /bin/ba                             sh

006d4000-006dd000 rw-p 000d4000 fd:00 1708138                            /bin/ba                             sh

006dd000-006e3000 rw-p 00000000 00:00 0

008dc000-008e5000 rw-p 000dc000 fd:00 1708138                            /bin/ba                             sh

010fe000-01140000 rw-p 00000000 00:00 0                                  [heap]

3a7ac00000-3a7ac20000 r-xp 00000000 fd:00 524708                         /lib64/                             ld-2.12.so

3a7ae20000-3a7ae21000 r--p 00020000 fd:00 524708                         /lib64/                             ld-2.12.so

3a7ae21000-3a7ae22000 rw-p 00021000 fd:00 524708                         /lib64/                             ld-2.12.so

3a7ae22000-3a7ae23000 rw-p 00000000 00:00 0

3a7b000000-3a7b002000 r-xp 00000000 fd:00 524716                         /lib64/                             libdl-2.12.so

3a7b002000-3a7b202000 ---p 00002000 fd:00 524716                         /lib64/                             libdl-2.12.so

3a7b202000-3a7b203000 r--p 00002000 fd:00 524716                         /lib64/                             libdl-2.12.so

3a7b203000-3a7b204000 rw-p 00003000 fd:00 524716                         /lib64/                             libdl-2.12.so

3a7b400000-3a7b58a000 r-xp 00000000 fd:00 524709                         /lib64/                             libc-2.12.so

3a7b58a000-3a7b78a000 ---p 0018a000 fd:00 524709                         /lib64/                             libc-2.12.so

3a7b78a000-3a7b78e000 r--p 0018a000 fd:00 524709                         /lib64/                             libc-2.12.so

3a7b78e000-3a7b790000 rw-p 0018e000 fd:00 524709                         /lib64/                             libc-2.12.so

3a7b790000-3a7b794000 rw-p 00000000 00:00 0

3a7d400000-3a7d41d000 r-xp 00000000 fd:00 524739                         /lib64/                             libtinfo.so.5.7

3a7d41d000-3a7d61c000 ---p 0001d000 fd:00 524739                         /lib64/                             libtinfo.so.5.7

3a7d61c000-3a7d620000 rw-p 0001c000 fd:00 524739                         /lib64/                             libtinfo.so.5.7

3a7d620000-3a7d621000 rw-p 00000000 00:00 0

7f80d28b0000-7f80d8744000 r--p 00000000 fd:00 1443800                    /usr/li                             b/locale/locale-archive

7f80d8744000-7f80d8751000 r-xp 00000000 fd:00 524320                     /lib64/                             libnss_files-2.12.so

7f80d8751000-7f80d8950000 ---p 0000d000 fd:00 524320                     /lib64/                             libnss_files-2.12.so

7f80d8950000-7f80d8951000 r--p 0000c000 fd:00 524320                     /lib64/                             libnss_files-2.12.so

7f80d8951000-7f80d8952000 rw-p 0000d000 fd:00 524320                     /lib64/                             libnss_files-2.12.so

7f80d8952000-7f80d8955000 rw-p 00000000 00:00 0

7f80d8958000-7f80d895a000 rw-p 00000000 00:00 0

7f80d895a000-7f80d8961000 r--s 00000000 fd:00 1444058                    /usr/li                             b64/gconv/gconv-modules.cache

7f80d8961000-7f80d8962000 rw-p 00000000 00:00 0

7fff0f58f000-7fff0f5a4000 rw-p 00000000 00:00 0                          [stack]

7fff0f5b4000-7fff0f5b5000 r-xp 00000000 00:00 0                          [vdso]

ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsysca                             ll]

==3998==

==3998== HEAP SUMMARY:    #评估堆内存,,,堆内存使用多大空间????评估的结果

==3998==     in use at exit: 0 bytes in 0 blocks

==3998==   total heap usage: 31 allocs, 31 frees, 40,552 bytes allocated

==3998==

==3998== All heap blocks were freed -- no leaks are possible        #所有的堆内存是空闲的,没有内存泄漏

==3998==

==3998== For counts of detected and suppressed errors, rerun with: -v

==3998== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 8 from 6)

[root@localhost ~]#



 什么叫内存泄漏?内存分出去了,别人不用了,释放不了了,始终处于被使用状态,,如果内存泄漏发生的话,一会儿泄漏一点,一会儿泄漏一点,长此下去,内存泄漏的比例过大时,可用内存就很小了,最后oom了,内存耗尽,,,,,,,,,有些程序员写的程序产生泄漏很正常,

观察内存泄漏的的一种方式:

        # valgrind --tool=memcheck cat /proc/$$/maps   

还有其它方式,比如监控某一个特定进程,使用watch -n 不间断的去观测某一个进程(某些进程)的pid,comm(命令),rss(常驻内存集),vsize(虚拟内存大小),如果 rss和vsize只增不减,就很可能泄漏了

        # watch -n1 'ps axo pid,comm,rss,vsize |  grep httpd'


也可以使用 sar -R 命令,来看一看系统范围内我们整体内存的分配情况,,如果 内存只往外分配,就是没有释放,或者始终是分配得多,释放的少,也意味着内存泄漏了,,,,,,,一定要长期观察,一会儿观察的不算

        # sar -R 1 120


内存泄漏主要观察的两个指标 rss, vsize,这两个是什么,以前马哥详细的解释过了,此处不讲了



如下图

Swap-out: 出去,从内存(系统)写到swap交换分区,

Swap-in:从swap交换分区读数据进内存,

哪些页面可能会被swap?

        Inactvie pages: 非活动页,通常将非活动页进行swap

        Anonymous pages: 匿名页,一般很少将匿名页进行swap


Swap cache,是swap读进来的,从swap加载进内存的,但没有在内存再做任何修改的数据,为什么称为swap cache,(因为把这个页面从内存删除,等会儿再从swap中读,还是可以读进来的),,,,swap cache可以有效的避免资源竞争,(尤其是多个进程访问同一个页框的时候的资源竞争),,,将一个swap读进来几次,每一次给一个进程,以避免资源竞争,

        Contains unmodified swapped-in pages        

        Avoids race conditions when multiple processes access a common page frame

image.png


如下图

如何提高swap性能?

1)降低swap的 think time??? (Defer swap until think time)????

意味着使用小swap分区 (Frequent, small swaps),

如果有必要的话,也可以将匿名页交换出去 (Swap anonymous pages more readily),因为匿名页里面通常都是些没修改的数据,,,当然这个功能我们管不了的,这是内核自己的功能

2)降低访问次数 (Reduce visit count),,,所以说尽量不要使用swap,,,,,,

        增大内存可以降低swap访问次数,

        我们可以使用多个交换分区,假如有多块硬盘,在每一块硬盘上都划分一个交换分区,让它们同时启用起来,而且让它们优先级一样,,,这样一来,当系统需要到交换分区上交换数据的时候,它会轮流使用多个交换分区,多个交换分区是负载均衡的,这样就能有效的降低每一个分设备的访问次数的,,,(如果优先级不一样,也是一个一个的使用的,也不能提高性能,,所以优先级要一样,,,,,,,,如果某个磁盘比较忙的话,那么就可以降低它的优先级),,,,如果只有一块硬盘,就没必划分多个swap分区了(除了增大寻道次数以外,没有任何有意义的帮助),,,,,,

3)降低服务时间 ( Reduce visit count ) 

        使用快速设备,比如弄一个SSD的盘(固态硬盘) 当swap来使用,就能够降低服务时间,,,,,,当然拿SSD盘当swap有点奢侈了,(当cache还可以,)

        把swap放在硬盘的最外道的分区上,(机械式硬盘,固定角速度,最外面的分区速度比较快,)


image.png


如下图

我们只有物理内存有空间,就不应该使用交换内存,如何调整这种策略?使用交换内存的概率怎么去调整

vm.swappiness 使用swap的倾向百分比, linux要不要将匿名页交换出去?将匿名页交换出去也可以提高性能的,默认情况下不会倾向于将匿名页交换出去的,如果倾向于将匿名页交换出去,调整vm.swappiness 

什么时候倾向于交换swappiness? 将内存映射为页面页表中的那些内存比例??????+vm.swappiness ,,如果大于等于100%,则开始使用交换内存(匿名页的swap交换内存),,,,,所以swappiness是一个调整参数,swappiness的默认值是60,,,,如果我们想让它更倾向于将匿名页交换出去的话,则调大swappiness的值(增大后,大于100的可能性会更大了),,,调小swappiness的值,则不倾向于交换出去,,,,,对于一个性能要求苛刻的场景中,我们应该调小此值的,,,,,,,,,,调大此值,只是让内存有更多的空间可用的,,,,,如果内存不够,倾向于将anonymous pages交换出去,在一定程度上可以提高性能,,,,因为page cache在一定程度上来讲,它更具有多次被访问的可能性,它尽量不应该被交换出去????????????

image.png



[root@localhost ~]# cat /proc/sys/vm/swappiness    #这是在红帽6上的值,在线帽5上值可能不一样

60

[root@localhost ~]#



如下图,

到底应该使用多大的交换内存

如果是批处理系统,是个科学计算的主机,比如matlib????进行大量科学计算的软件的话,就是4 倍的ram

如果是数据库服务器的话,就小于等于1G,,,,,,,,数据库服务器无论如何,尽量不应该使用swap

如果是应用程序服务器,比如web server,则为ram的一半左右

image.png



如下图,

如保调整swap的think time?

使用vm.page_cluster(页组,页簇),一次性一批挪进多少

vm.swap_token_timeout 这个用得很少,不用介绍了


image.png


如下图

怎么去调优swap的性能,不得不用swap的情况下)

在多个设备(磁盘)上多建几个分区,轮流使用,优先级(pri)(priority)一样,,,如果某个设备慢,作为补充性的使用,让它优先级变低,,,

注意我们这里使用pri=几,本来默认使用defaults的

 swapon -a

         View active swap devices in /proc/swaps

image.png



如下图

怎么去监控内存使用的,下面的命令,昨天马哥已讲

Memory activity #内存活动        disk????命令也能观察

        vmstat -n [interva1] [count]

        sar -r [interva1] [count]

                Report memory and swap space utilization statistics

Rate of change in memory

        sar -R [interval] [count]        #memory的变化速率 disk????也可以

                 Report memory statistics

Swap activity

        sar -W [interva1] [count]    #Swap activity使用 sar -W来监控

                 Report swapping statistics

All IO

        sar -B [interva1] [count]        #监控IO的活动状况,报告页面唤进唤出等相关情况

                 Report paging statistics

image.png


[root@localhost ~]# sar -B 1

Linux 2.6.32-754.el6.x86_64 (localhost.localdomain)     2021年07月26日  _x86_64_

#最关键的是 pgpgin/s pgpgout/s,,如果有大量的页面读进读出的话,说明I/O活动量比较大


09时09分29秒  pgpgin/s pgpgout/s   fault/s(#一般叫min fault????啥意思)  majflt/s(# major fault)  pgfree/s(页面释放的每秒钟的平均的个数) pgscank/s(扫描个数) pgscand

09时09分30秒      0.00      0.00     87.00      0.00    123.00      0.00      0.

09时09分31秒      0.00      0.00     40.00      0.00    112.00      0.00      0.

09时09分32秒      0.00      0.00     32.00      0.00    117.00      0.00      0.

09时09分33秒      0.00      0.00     32.32      0.00    112.12      0.00      0.

09时09分34秒      0.00      0.00     31.68      0.00    109.90      0.00      0.

09时09分35秒      0.00      0.00     32.00      0.00    111.00      0.00      0.

09时09分36秒      0.00      0.00     32.00      0.00    112.00      0.00      0.

09时09分37秒      0.00      0.00     34.00      0.00    115.00      0.00      0.

09时09分38秒      0.00      0.00     32.00      0.00    111.00      0.00      0.

09时09分39秒      0.00      0.00     32.32      0.00    112.12      0.00      0.

09时09分40秒      0.00     12.00     32.00      0.00    112.00      0.00      0.

09时09分41秒      0.00      0.00     31.68      0.00    109.90      0.00      0.

09时09分42秒      0.00      0.00     32.00      0.00    111.00      0.00      0.

^C

[root@localhost ~]# 


如下图

我们要完成内存的分配(包括申请,释放(回收)),由Slab Allocator和buddy system,,,,,,,,,,,,,,将线性地址映射为物理地址的是MMU,,,,pdflush会每隔一段时间清洗物理内存中的数据到磁盘上,,,,,,,,,,,,,,kswapd是监控页面往交换内存当中的唤进唤出的,,,,,,,,,,,我们调的参数主要就是控制这些子系统的工作的

image.png


我们调的参数有:

    HugePage: 提高TLB的性能,而且能增加内存分配效率的

    IPC: IPC通信的,ipc包括共享内存和msg

    pdflush:

    slab

    swap

            跟swap相关的调整包括了缓存匿名页的倾向性  swappiness,,,为了提高swap的性能可以轮流使用多个不同设备上的交换分区        

    oom




https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/index



  1. #5.4. Capacity Tuning    #调整Capacity

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-memory-captun

overcommit#关于过量使用的

Capacity-related Kernel Tunables    #ipc通信的??????

aio    #关于aio的可以不用调

Out-of-Memory Kill Tunables    #关于oom的

file-max    #系统也会自动计算,不需要调



  1. #5.5. Tuning Virtual Memory  调整虚拟内存的

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-memory-tunables


swappiness

min_free_kbytes    #应该调小,,但这个调太大或太小都有风险

dirty_ratio

dirty_background_ratio

drop_caches




内存子系统的调优,关键是要理解内存子系统的工作原理,,,,,不然的话,也无法理解虚拟化技术所面临的困境,以及为什么采取这么多复杂的措施来解决这样的问题,



I/O, Filesystem(文件子系统), Network(网络调优),,,,,,,,,,这三个简单点,,,,,,,,,,,,,,,,,,,,,

,Network反而是将来我们调优的时候需要修改参数相关的地方,从网上搜索文档最多的一个,,,,,里面有一堆参数,比如实现TCP线程的重用等,,,,,

 Filesystem文件系统这里面,马哥讲讲怎么使用文件系统性能评估工具,对它做压力测试,看看哪一种性能更好

I/O会讲几个I/O调度器,如deadline,CFQ,还有NOOP





普通分类: