• Linux系统调优


    原文: http://roqi410.blog.51cto.com/2186161/671708


    Linux在进行系统调优的时候,首先要考虑整个操作系统的结构,然后针对各个部分进行优化,下面展示一个Linux系统的各个组成部分:

    有上图可以看出,我们可以调整的有应用程序,库文件,内核,驱动,还有硬件本身,所以接下来讲对这些进行详细的介绍,从而是系统的性能有所提高。
    内核子系统中主要包括一下几个方面:
    1.         network(网络)
    2.         IO(输入输出子系统)
    3.         process(进程)
    4.         memory(内存)
    5.         File System(文件系统)
    一、    Linux的进程管理
    1、进程的定义:进程是计算机资源分配单位,主要包括对系统资源的调度,如CPU时间,内存空间,是一个程序执行的一个副本。他们还包括一系列的资源,如文件的打开,释放信号,内核内的数据,进程状态,内存地址的映射,执行的多个线程,和数据段的全局变量。
    2、进程状态:running(运行)、interruptible(可中断的睡眠态)、unitertible(非可中断的睡眠态)、stopped(停止状态)、zombie(僵死态)

     
    Task_Running:一个进程要么在CPU上执行,要么等待CPU的时间再执行;
    Task_Interruptible:一个处于sleeping状态的进程,直到环境条件改变,重新挂起一个硬件中断,使用系统释放的资源,或者释放一个信号,这个信号可以唤醒这个进程到Task_Running状态,一般是一个IObound类型的;
    Task_uninterruptible:这个和Task_Interruptible是一样的,但是CPU bound类型的。
    Task_stopped:程序执行已经完成,这个进程在接受到SIGSTOP、SIGTSTP, SIGTTIN, or SIGTTOU signal这些信号的时候,这个进程进入这个状态;
    Task_zombie:子进程执行完成,但是该子进程的父进程已近dead,无法回收这个子进程所占用的资源;
    3、进程周期:一个子进程都是父进程的一个副本,所以除了PID和PPID不同,其他的都是相同的,而子进程在执行一个程序的时候,需要在单独在一个地址空间内进行,当执行完成之后,子进程锁占用的资源要有父进程进行回收,这就是一个进程的生命周期;
    4、线程的概念:线程是比进程资源更小的资源调度单位,所以也叫轻量级的进程(LWP)
    而线程的调度更加节省系统的资源,如果使用的是进程,即使是相同的进程也需要分配两份资源,而线程就不同了,它可以在同一个进程中实现资源的重复利用,这就是nginx的性能比使用apache性能要好的原因,因为nginx是基于线程的,而apache的prefork模式的是基于进程的,每一个进程连接都要分配4M的空间,而每一个线程确非配4k由此可以找出显著的差别了,关于进程和线程资源调分配对比,我给大家准备了一个图,可以简单的看出他们之间的区别:

    5、进程的调度:进程调度就是按照一定的调度算法,来实现不同进程之间的切换,常见的调度算法有一下几种:
    O(1)调度器<2.6之后>这种在调度的时候一秒一个,能实现公平的调度,公平分配时间,但是再有的时候会浪费时间,如edit和movie之间,edit就会浪费时间。
    O(log n)
    O(n)
    O(n^2)
    O(2^n)
    为了解决O(1)的不足,又引用了deadline,deadline有三个队列,活动队列,死亡队列,deadline队列,为不同的进程做一个计数器,到时间就不管进程优先级的高低,而是“见死就救”。(deadline现在在磁盘上使用)现在进程调度使用的是CFS(完全公平调度算法)调度算法:不再为每一个进程分配一个时间片,而是按照进程来分配一个时间比例。
    6、进程的种类:交互式进程、批处理进程、实时进程;
    7、进程的优先级:
     静态优先级:1-99,100-139
     动态优先级:动态优先级调整的范围100-139,通过调整nice值进行调整,调整后表现为nice值。nice值范围在-20—19
     实时优先级:0-99(数字越大,优先级越高)
    8、进程调度策略:
     SCHED_FIFO:先进先出【1-99】,只能调度实时优先级进程;
     SCHED_RR:轮调 引入了时间片,是FIFO改进后的算法,只能调度实时优先级进程;
     SCHED_OTHER:调度传统的分时进程【100-139】;
     SCHED_BATCH:只用来调度nice=0或优先级为120的;
     使用#ps axo comm.,rtprio显示实时优先级;
     
    实时进程定义启动使用的调度类别和指定优先级:
    chrt  -f [1-99] /path/to/program arguments //添加到FIFO队列中去
    chrt  -r [1-99] /path/to/program arguments //添加到RR队列中
    nice&&renice调整优先级
    查看系统的瓶颈是否是CPU
    1.平均负载 yum install sysstat
     负载的三个平均值不能大于3
     w  
     uptime
     top
     sar -q 1 3 
     vmstat 1 5
    2.CPU的利用率
     mpstat -p 60%在用户空间就是正常的
     sar -P ALL 1
     iostat -c 1 
     cat /proc/stat
    9、cache 缓存:
    缓存分为cache-hit和cache-miss
    #yum install x86info
    #x86info –c 查看cpu的缓存类型
    #valgrind --tool=cachegrind ls 查看缓存命中情况
    # dmesg | grep -i cache 查看缓存大小
    10、多个CPU和多核CPU之间进行均衡
    #watch -n .5 'ps axo comm,pid,psr | grep httpd ' 查看进程在哪个CPU上
    taskset [opts]
    #taskset -c -p CPULIST PID 把某一个进程绑定到一个特定的CPU上
    #taskset -c -p 0 5533 把5533进程绑定到0号CPU上
    这种能提高缓存命中率,但是对均衡有缺陷
    11、调度域:就是将某些进程绑定在多个CPU组成的域中。调度域的作用就是把CPU组定义为调度域,一个CPU集合就是一个调度域,配置本地调度域:
    #mkdir /cpusets
    #vim /etc/fstab 添加一下内容
    cpuset     /cpusets   cpuset     default    0 0
    #cd /cpusets
    #ls

    #mkdir ro

    #cd ro
    #echo 0 > cpus 这样就建立了一个ro的调度域,同时绑定到第一个CPU上了;
    12、进程的地址空间
    一个进程在使用自己的内存空间进行工作的,所以这就导致了每一进程都有自己的地址空间,每一个进程都有自己的特点和数据大小,进程必须持有大量的数据尺寸,对于Linux内核来说,每个进程使用动态内存分配的是结构化的,具体如下图所示:

    所以进程可以分为代码段、数据段、BBS、堆、栈。
     
    二、      内存管理
    1、内存管理要想了解内存的调度机制,下面我就结合下图进行简单的阐述:

    我就从左向右一步一步的介绍用户发出个请求,通过调用库文件,有用户空间进入内核空间,在内核空间中把数据从磁盘中读入内存中进行操作,操作完成之后,在同步到磁盘中,而为了提高CPU的工作效率,使用MMU(memory manger unit,内存管理单元)来替代CPU来执行整个进程的调度,在这个过程中,首先要交换分区slab allocator目录找到对应的资源所在的位置,然后到对应的内存空间或磁盘空间中去寻找,当然为了避免内存回收的外碎片,引入了zoned buddy allocator,这个就是合理分配内存资源的,等到进程调度占用的空间使用完成之后,需要回收资源,这里就是用到了pdflush,就是讲内存中dirty pages的数据同步到磁盘上去。
    PTE:page tables 页表项
    PAE:物理地址扩展
    TLB:transition lookaside buffers 转换后缓冲器
    只用x86info –c 和 dmesg可以查看
    2、内存空间结构:
    下图是对32位的系统和64位的系统内存空间的一个对比

    由于硬件设备的限制,所以内核不能把所以的page视为相同的,所以出现了如上图的Zone,下面开始详细的介绍这些内容了:
    1.在32位的系统上一个单独的进程最大的地址空间是4G(2^32),这4G被分为1G的内核空间和3G的用户空间;其中1G的内核空间是用来做页表的虚拟地址和物理地址进行映射关系的,另外3G是用户空间;
    在1G的内核空间中,其中有16MB是用来做DMA(直接内存区域)的,这个区域包括pages;从16MB-896MB这期间的880MB是内核使用的,还有128MB是用来做映射的,从虚拟地址空间映射到物理地址空间上去;而上面的3G就是整整的地址空间了。而对于64位的操作系统的空间,有1G是用来做DMA的,区域的都是用来做实际的地址空间的,所以在服务器上,不带考虑的直接装64位的系统;
    2. 通常出现缺页异常的原因:数据还在磁盘上、数据在交换分区上,如果数据持续从交换分区上进行数据调度的话,那么这就直接可以断定是内存瓶颈,内存不够用,剩下的就不解释了,你懂的,扩展内存,呵呵!
    3.查看各个进程的资源使用情况的方法:
    #cat /proc/PID/status 或cat /proc/PID/statm
    然后你就可以查看一下里面的内容了,系统每启动一个进程,都会占用一定的地址空间。
    也可以使用图形化界面进行查看
    #gnome-system-monitor
    #pmap +PID 查看进程对应的库文件,也可以定位内存的瓶颈
     
    #yum install glibc-utils
    #memusage +COMMAND 查看单个进程占用的内存,同时以条形框的形式展示
    #memusage –help可以获取该命令的更多的帮助信息

    #ps axo minflt,majflt 看所有进程的缺页异常发生情况

    其中minflt表示的是磁盘的使用情况,而majflt表示交换分区使用的情况,根据这些信息可以判断,如果长期使用交换分区的话,那么就是内存瓶颈了。
    4.内存的配额分为一下几种:
     (1)Process forks or execs child process
    (2)New process requests memory
    (3)New process uses memory
    (4)Process frees memory
    5.内存的类型:
    SRAM:静态(static RAM)
    DRAM:动态 (Dynamic RAM)
       SDRAM
       DDR
       RDRAM(服务器上使用,窄带,有奇偶校验的内存)
    6、提高TLB的性能
    TLB:(transition lookais buffer)转换后援缓冲器,就是存放虚拟地址到物理地址转换的表,也称为页表缓冲;
    TLB存放的页面在32位系统上支持4k和4M两种,在其他系统上就更多了,如果想了解,可以借助帮助文档
    #yum install kernel-doc
    安装完成之后位于 /usr/share/doc/kernel-doc-2.6.18/Documentation中;
    如果我们想让TLB的值大点,也就是做成Hugetlb Page(大页表)可以设置内核参数,这样可以提高TLB缓存的命中率,降低PTE的方位次数,来加速地址转换的速度;
    调整TLB值的大小:
    /etc/sysctl.conf
     vm.nr_hugepages=n
    临时生效:
     #echo 4 > /proc/sys/vm/nr_hugepages
     #sysctl -w vm.nr_hugepages=n
    永久有效:
     #vim /etc/sysctl.conf
     #sysctl -p 保存,生效
    为了以后使用大页表,我们可以做一个大页表文件系统
    #mkdir /hugepages
    #mount -t hugetlbfs none /hugepages 在以后就如果使用到了,就可以直接使用了;
    当然为了详细的观察进程详细的调度情况,也可以追踪系统调用
    #strace -p PID 查看进程详细调度的进程
    #strace ls 可以看到所发出指令的详细的系统调用
    #strace ls -o /tmp/tmp.txt 保存在指定的文件中。
    #strace -c -p PID 统计系统调用时间和所调用的次数,结合这些结果进行分析
    7、内存使用应遵循的策略:
     a.减小内存小对象的消耗,使用的工具有slab cache
     b.降低那些比较慢的系统服务时间:
        i.文件系统的:buffer cache(slab cache)
        ii.DISK IO: page cache
        iii.Internetprocess:shared memory
        iv.network IO:buffer cache,arp cache,connection tracking (buffer是解决两端速率不匹配的,而cache是为了重复使用,提高缓存命中率的)
    结合上面的理论,接下来就是做详细的内存内核参数的调整的过程了:
    1、vm.min_free_kbytes 至少要在内存中保留多大的K字节的空间
     说明:当一个应用反复使用和释放大的内存,磁盘的带宽下,CPU使用低下,内存小,需要改变上面的参数,如果改小了,这样就会导致服务时间降低,其他应用程序无法有足够的内存,对zone_nomal照成很大的压力;默认是2890
    2、vm.overcommit_memory 内存过度使用,这个参数有三个数值可以设置0,1,2
    0|拒绝过度使用(默认)
     1|总是过度使用 (不建议)
     2|仅能使用所有的RAM和swap的一个百分比建议设置为30,50%已经是大的了<这个对启动2才有效>)尽可能根据committed_AS为参照来设置
    3、vm.overcommit_ratio 过度使用的比,就是上面swap的比(建议设置为30%,50%已经是较大的了)默认:50
    4、调整slab缓存小内存对象,缓存的是文件的innode(索引),每一种slab只能缓存一中小内存对象;
    该文件在/proc/slabinfo文件中,我们可以看一下:

    这个问价中可以该的值有limit,batchcount,sharedfactor,其中limited=N*batchcount
    如:
    #echo “ext3_inode_cache 108 27 8 >/proc/slabinfo
    #slabtop //查看当前slab分配的信息
    同样可以使用vmstat –m 也可以查看当前slab分配信息

    5、调整ARP cache:
    #cat /proc/net/arp

    可以看出现在arp缓存
    也可以使用一下命令进行查看
    #arp –a
    #ip neigh show
    arp -d hostname 删除arp缓存
    ip neighbor flush dev eth0 标记为失效,过一会就会清空
    当让为了减少arp cache占用系统资源,可以设置其存储的条目
    net.ipv4.neigh.default.gc_thresh1 定义缓存上线,当缓存大于多少的时候就做清理(默认128)
    net.ipv4.neigh.default.gc_thresh2 软上线 512
    net.ipv4.neigh.default.gc_thresh3 硬上线 1024
    net.ipv4.neigh.default.gc_interval 缓存收集垃圾时间 默认30s
    这些是对arp缓存大小的设置;
    6、page cache :page缓存的是数据;
    使用到的场所:直接读、读写、读写快设备、访问内存mapped files、访问swap mapped files
    vm.lowmem_reserve_ratio 低地址空间中预留的空间的百分比,一般指的是zone_normal放置OOM(内存地址耗尽);
    vm.vfs_cache_pressure 定义内核回收slab cache、pagecache、swapcache中的内存的倾向性,默认是100,如果小于100,倾向性变小,如果设置为0,就不会回收pagecache、swapcache中的内存(不建议),如果经常打开文件,要增大这个值,能快速回收内存,如果有足够大的内存,可以维持在100,一般不需要降低这个值;
    vm.page_cluster 页簇:控制物理内存数据交换到交换分区的时候,一次交换的多少个页面数2^n 这个值默认是3,也就是8个页面,应用程序频繁使用交换分区的时候,可以调大点;
    vm.zone_reclaim_mode 内存区域回收的模型,当一个区域的内存消耗完的时候,如何回收此区域的空间,其值有:1(打开回收机制)、2(将此内存的章页同步到磁盘在回收)、4(回收交换页面所占用的空间)
    7、anonymous pages:匿名页面
    匿名页面主要包括程序数据,arrarys,heap,allowcations等

    8、SysV IPC interprocess communication 进程间通信:
    *1.semaphores 信号
    调整:
    kernel.sem
    cat /proc/sys/kernel/sem
    250 每个数组信号量
    32000
    32
    128 可以所使用的数组
    *2.Messageing queues 消息队列(rubbit MQ)通过交换信息
    调整:
    kernel.msgmnb
    16384 一个单独的消息队列能容纳多少消息信号
    kernel.msgmni
    16 消息队列最大消息队列数
    kernel.msgmax
    8192 单个消息最大上线8k
    *3.shared memory 共享内存
    调整:
    kernel.shmmni
    4096 共享内存段的最大数目
    kernel.shmall
    2097152 一次共享页面的值
    kernel.shmmax
    shmall*4k 共享内存段的大小可以被创建
     
    使用ipcs命令查看当前机器进程间通信的机制
    ipcs -l显示进程间通信的限制

    如果文件的修改不是太多,可以把数据放在/dev/shm中,这个直接写入内存,但是一旦断电,数据就会丢失
     
    9、内存详细使用情况的命令:
    free -m 显示内存使用情况
    page tables:cat /proc/vmstat 
    system memory:cat /proc/meminfo (total physical memory,cache,active use,inactive) 使用vmstat -s
    #yum install sysstat
    sar -r 1 10 (每个一秒取一次,取十次)
     
    10、页面分类:
    1.free 
    2.inactive clean 可以被直接回收使用
    3.inactive dirty 页面中有数据没有同步到磁盘上去,只要同步到磁盘上去了,就能回收
    4.active 正在被使用的页面
     
    Bubby system:伙伴系统,是避免内存回收的外碎片的,保存内存空间是连续的一片空间
     
    内核中的有个线程叫kswapd来回收空闲分区,把内存中使用较少的(非活动clean状态的)放到交换分区,腾出空间供其他的使用
     
    使用vmstat -a |-s 显示页框使用状态
     
    页面主要作用:page cache 和进程地址空间,所有回收page cache中的页面
     
    11、如何回收dirty pages:
    1.同步到磁盘上,靠的是pdflush的内核线程(每隔一段时间就会同步,可以多个同时运行的,可以定义pdflush的数目,如CPU,DISK多,可以在一个CPU上一个,提高并发能力)
    2.放到交换分区
    vm.nr_pdflush_threads 就是定义pdflush线程个数,建议一个磁盘一个pdflush线程
    vm.dirty_background_ratio 当脏页总数占整个内存比例的时候,启动pdflush
    vm.dirty_ratio 某一个单进程的脏页所占用的比例,然后启动pdflush进行刷写
    vm.dirty_expir_centisecs 每隔一段时间进行一次刷写操作(默认30s,0表示禁用)
    vm.dirty_writeback_centisecs 默认5s,定义一个数据修改超过这个时间就可以刷写了
     
    12、如何回收干净页面:
    sync
    fsync
    echo s > /proc/sysrq-trigger   手动同步到磁盘
    echo x > /proc/sys/vm/drop_caches
    x=
     1 free pagecache 
     2 free dentries and inodes
     3 buffer and cache
    out-of-memory killer进程在内存占用满了,就开始杀死一些进程
    /proc/PID/oom_score 进程的分数,分数越大,就会在内存oom的时候最先杀死
     
    13、优化OOM策略:
    echo n >/proc/PID/oom_adj
    echo f > /proc/sysrq-trigger 手动杀死进程
    vm.panic_on_oom=1 禁止oom-kill ,但是内存耗尽也会照成系统恐慌
     
    14、探测内存泄漏:一个进程退出的时候,内存未释放
    内存泄漏分为两种:
     1.虚拟(virtual)内存泄漏:只申请,但不使用
     2.real:内存释放失败
    #sar -R 查看内存申请、释放情况,正数是申请的,负数是释放,其中frmpgz正好相反
    #yum install valgrind
    #valgrand --tool=memcheck ls 查看内存泄漏
    **作为管理员要经常关注内存是否泄漏
     
    15、swap 交换分区:
    swap-out=page-out 就是把内存中的数据放到交换分区
    swap-in :把内存中的数据放到交换分区;
     
    那些pages要进行交换:
    inactive pages
    anonymous pages
     
    16、提高swap的性能:
    1.降低决策时间 :快速换入唤出小页面,匿名pages
    2.降低访问次数:做swap集群,多个分区做相同的优先级
    3.降低服务时间:尽可能使用分区,不实用文件;尽量把交换分区放到磁盘外道;把交换分区放到raid0上
    vm.swappiness 定义多大倾向唤出交换分区的匿名页,里面是一个%比,达到了就使用交换内存,如果不想使用交换分区,可以把值设置小于100,默认是60
     
     
    17、交换分区的大小:
    批处理服务:> 4*RAM
    数据库服务:<=1G
    应用程序服务:>=0.5*RAM
     
    vm.page_cluster=n (2^n个页面)
    vm.swap_token_timeout 一旦发现交换分区频繁的不参与这个的时间
     
    18、监控内存工具:
    vmstat -n 显示内存和swap分区的数据
    sar -r 显示内存和swap分区的数据
    sar -R 显示内存的数据
    sar -W 像是swqp数据
    sar -B 显示页面的数据
     

    还有网络、IO调优待续。。。

  • 相关阅读:
    ulimit -a
    nginx check_http_send type=http 查检测不到后端TOM的存活
    通过ip查找能应机器的MAC
    错误状态码URL重定向
    error_page 改变状态码为新的状态码,并显示指定内容
    使用 CefSharp 在 C# App 中嵌入 Chrome 浏览器
    C#客户端嵌入Chrome浏览器的实现
    Task.Run c#启动线程
    C#利用webBrowser怎么去掉网页中不想显示的部分
    InDesign CC 2019安装包+破解
  • 原文地址:https://www.cnblogs.com/aquester/p/9891831.html
Copyright © 2020-2023  润新知