首页 » PHP教程 » php0108技巧_Linux机能优化大年夜全

php0108技巧_Linux机能优化大年夜全

duote123 2024-12-08 0

扫一扫用手机浏览

文章目录 [+]

运用负载角度:直接影响了产品终真个用户体验系统资源角度:资源利用率、饱和度等

性能问题的实质便是系统资源已经到达瓶颈,但要求的处理还不足快,无法支撑更多的要求。
性能剖析实际上便是找出运用或系统的瓶颈,设法去避免或缓解它们。

选择指标评估运用程序和系统性能为运用程序和系统设置性能目标进行性能基准测试性能剖析定位瓶颈性能监控和告警

对付不同的性能问题要选取不同的性能剖析工具。
下面是常用的Linux Performance Tools以及对应剖析的性能问题类型。

php0108技巧_Linux机能优化大年夜全

到底该当怎么理解”均匀负载”

均匀负载:单位韶光内,系统处于可运行状态和不可中断状态的均匀进程数,也便是均匀生动进程数。
它和我们传统意义上理解的CPU利用率并没有直接关系。

php0108技巧_Linux机能优化大年夜全
(图片来自网络侵删)

个中不可中断进程是正处于内核态关键流程中的进程(如常见的等待设备的I/O相应)。
不可中断状态实际上是系统对进程和硬件设备的一种保护机制。

均匀负载多少时合理

实际生产环境中将系统的均匀负载监控起来,根据历史数据判断负载的变革趋势。
当负载存在明显升高趋势时,及时进行剖析和调查。
当然也可以当设置阈值(如当均匀负载高于CPU数量的70%时)

现实事情中我们会常常稠浊均匀负载和CPU利用率的观点,实在两者并不完备对等:

CPU 密集型进程,大量 CPU 利用会导致均匀负载升高,此时两者同等I/O 密集型进程,等待 I/O 也会导致均匀负载升高,此时 CPU 利用率并不一定高大量等待 CPU 的进程调度会导致均匀负载升高,此时 CPU 利用率也会比较高

均匀负载高时可能是 CPU 密集型进程导致,也可能是 I/O 繁忙导致。
详细剖析时可以结合 mpstat/pidstat 工具赞助剖析负载来源。

CPUCPU高下文切换(上)

CPU 高下文切换,便是把前一个任务的 CPU 高下文(CPU 寄存器和 PC)保存起来,然后加载新任务的高下文到这些寄存器和程序计数器,末了再跳转到程序计数器所指的位置,运行新任务。
个中,保存下来的高下文会存储在系统内核中,待任务重新调度实行时再加载,担保原来的任务状态不受影响。

按照任务类型,CPU 高下文切换分为:

进程高下文切换线程高下文切换中断高下文切换进程高下文切换

Linux 进程按照等级权限将进程的运行空间分为内核空间和用户空间。
从用户态向内核态转变时须要通过系统调用来完成。

一次系统调用过程实在进行了两次 CPU 高下文切换:

CPU 寄存器中用户态的指令位置先保存起来,CPU 寄存器更新为内核态指令的位置,跳转到内核态运行内核任务;系统调用结束后,CPU 寄存器恢复原来保存的用户态数据,再切换到用户空间连续运行。

系统调用过程中并不会涉及虚拟内存等进程用户态资源,也不会切换进程。
和传统意义上的进程高下文切换不同。
因此系统调用常日称为特权模式切换。

进程是由内核管理和调度的,进程高下文切换只能发生在内核态。
因此比较系统调用来说,在保存当提高程的内核状态和CPU寄存器之前,须要先把该进程的虚拟内存,栈保存下来。
再加载新进程的内核态后,还要刷新进程的虚拟内存和用户栈。

进程只有在调度到CPU上运行时才须要切换高下文,有以下几种场景:CPU韶光片轮流分配,系统资源不敷导致进程挂起,进程通过sleep函数主动挂起,高优先级进程抢占韶光片,硬件中断时CPU上的进程被挂起转而实行内核中的中断做事。

线程高下文切换

线程高下文切换分为两种:

前后线程同属于一个进程,切换时虚拟内存资源不变,只须要切换线程的私有数据,寄存器等;前后线程属于不同进程,与进程高下文切换相同。

同进程的线程切换花费资源较少,这也是多线程的上风。

中断高下文切换

中断高下文切换并不涉及到进程的用户态,因此中断高下文只包括内核态中断做事程序实行所必须的状态(CPU寄存器,内核堆栈,硬件中断参数等)。

中断处理优先级比进程高,以是中断高下文切换和进程高下文切换不会同时发生

CPU高下文切换(下)

通过 vmstat 可以查看系统总体的高下文切换情形

vmstat 5 #每隔5s输出一组数据procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 103388 145412 511056 0 0 18 60 1 1 2 1 96 0 0 0 0 0 103388 145412 511076 0 0 0 2 450 1176 1 1 99 0 0 0 0 0 103388 145412 511076 0 0 0 8 429 1135 1 1 98 0 0 0 0 0 103388 145412 511076 0 0 0 0 431 1132 1 1 98 0 0 0 0 0 103388 145412 511076 0 0 0 10 467 1195 1 1 98 0 0 1 0 0 103388 145412 511076 0 0 0 2 426 1139 1 0 99 0 0 4 0 0 95184 145412 511108 0 0 0 74 500 1228 4 1 94 0 0 0 0 0 103512 145416 511076 0 0 0 455 723 1573 12 3 83 2 0cs (context switch) 每秒高下文切换次数in (interrupt) 每秒中断次数r (runnning or runnable)就绪行列步队的长度,正在运行和等待CPU的进程数b (Blocked) 处于不可中断就寝状态的进程数

要查看每个进程的详细情形,须要利用pidstat来查看每个进程高下文切换情形

pidstat -w 514时51分16秒 UID PID cswch/s nvcswch/s Command14时51分21秒 0 1 0.80 0.00 systemd14时51分21秒 0 6 1.40 0.00 ksoftirqd/014时51分21秒 0 9 32.67 0.00 rcu_sched14时51分21秒 0 11 0.40 0.00 watchdog/014时51分21秒 0 32 0.20 0.00 khugepaged14时51分21秒 0 271 0.20 0.00 jbd2/vda1-814时51分21秒 0 1332 0.20 0.00 argusagent14时51分21秒 0 5265 10.02 0.00 AliSecGuard14时51分21秒 0 7439 7.82 0.00 kworker/0:214时51分21秒 0 7906 0.20 0.00 pidstat14时51分21秒 0 8346 0.20 0.00 sshd14时51分21秒 0 20654 9.82 0.00 AliYunDun14时51分21秒 0 25766 0.20 0.00 kworker/u2:114时51分21秒 0 28603 1.00 0.00 python3cswch 每秒志愿高下文切换次数(进程无法获取所需资源导致的高下文切换)nvcswch 每秒非志愿高下文切换次数(韶光片轮流等系统逼迫调度)

vmstat 1 1 #新终端不雅观察高下文切换情形此时创造cs数据明显升高,同时不雅观察其他指标:r列:远超系统CPU个数,解释存在大量CPU竞争us和sy列:sy列占比80%,解释CPU紧张被内核占用in列:中断次数明显上升,解释中断处理也是潜在问题

解释运行/等待CPU的进程过多,导致大量的高下文切换,高下文切换导致系统的CPU占用率高

pidstat -w -u 1 #查看到底哪个进程导致的问题

从结果中看出是 sysbench 导致 CPU 利用率过高,但是 pidstat 输出的高下文次数加起来也并不多。
剖析 sysbench 仿照的是线程的切换,因此须要在 pidstat 后加 -t 参数查看线程指标。

其余对付中断次数过多,我们可以通过 /proc/interrupts 文件读取

watch -d cat /proc/interrupts

创造次数变革速率最快的是重调度中断(RES),该中断用来唤醒空闲状态的CPU来调度新的任务运行。
剖析还是由于过多任务的调度问题,和高下文切换剖析同等。

某个运用的CPU利用率达到100%,怎么办?

Linux作为多任务操作系统,将CPU韶光划分为很短的韶光片,通过调度器轮流分配给各个任务利用。
为了掩护CPU韶光,Linux通过事先定义的节拍率,触发韶光中断,并利用全局变了jiffies记录开机以来的节拍数。
韶光中断发生一次该值+1.

CPU利用率,除了空闲韶光以外的其他韶光占总CPU韶光的百分比。
可以通过/proc/stat中的数据来打算出CPU利用率。
由于/proc/stat时开机以来的节拍数累加值,打算出来的是开机以来的均匀CPU利用率,一样平常意义不大。
可以间隔取一段韶光的两次值作差来打算该段韶光内的均匀CPU利用率。
性能剖析工具给出的都是间隔一段韶光的均匀CPU利用率,要把稳间隔韶光的设置。

CPU利用率可以通过top 或 ps来查看。
剖析进程的CPU问题可以通过perf,它以性能事宜采样为根本,不仅可以剖析系统的各种事宜和内核性能,还可以用来剖析指定运用程序的性能问题。

perf top / perf record / perf report (-g 开启调用关系的采样)

sudo docker run --name nginx -p 10000:80 -itd feisky/nginxsudo docker run --name phpfpm -itd --network container:nginx feisky/php-fpmab -c 10 -n 100 http://XXX.XXX.XXX.XXX:10000/ #测试Nginx做事性能

创造此时每秒可承受要求给长少,此时将测试的要求数从100增加到10000。
在其余一个终端运行top查看每个CPU的利用率。
创造系统中几个php-fpm进程导致CPU利用率骤升。

接着用perf来剖析详细是php-fpm中哪个函数导致该问题。

perf top -g -p XXXX #对某一个php-fpm进程进行剖析

创造个中 sqrt 和 add_function 占用 CPU 过多, 此时查看源码找到原来是sqrt中在发布前没有删除测试代码段,存在一个百万次的循环导致。
将该无用代码删除后创造nginx负载能力明显提升

系统的CPU利用率很高,为什么找不到高CPU的运用?

sudo docker run --name nginx -p 10000:80 -itd feisky/nginx:spsudo docker run --name phpfpm -itd --network container:nginx feisky/php-fpm:spab -c 100 -n 1000 http://XXX.XXX.XXX.XXX:10000/ #并发100个要求测试

实验结果中每秒要求数依旧不高,我们将并发要求数降为5后,nginx负载能力依旧很低。

此时用top和pidstat创造系统CPU利用率过高,但是并没有创造CPU利用率高的进程。

涌现这种情形一样平常时我们剖析时遗漏的什么信息,重新运行top命令并不雅观察一会。
创造就绪行列步队中处于Running状态的进行过多,超过了我们的并发要求次数5. 再仔细查看进程运行数据,创造nginx和php-fpm都处于sleep状态,真正处于运行的却是几个stress进程。

下一步就利用pidstat剖析这几个stress进程,创造没有任何输出。
用ps aux交叉验证创造依旧不存在该进程。
解释不是工具的问题。
再top查看创造stress进程的进程号变革了,此时有可能时以下两种缘故原由导致:

进程一直的崩溃重启(如段缺点/配置缺点等),此时进程退出后可能又被监控系统重启;短时进程导致,即其他运用内部通过 exec 调用的表面命令,这些命令一样平常只运行很短韶光就结束,很难用top这种间隔较长的工具来创造

可以通过pstree来查找 stress 的父进程,找出调用关系。

pstree | grep stress

创造是php-fpm调用的该子进程,此时去查看源码可以看出每个要求都会调用一个stress命令来仿照I/O压力。
之前top显示的结果是CPU利用率升高,是否真的是由该stress命令导致的,还须要连续剖析。
代码中给每个要求加了verbose=1的参数后可以查看stress命令的输出,在中断测试该命令结果显示stress命令运行时存在因权限问题导致的文件创建失落败的bug。

此时依旧只是预测,下一步连续通过perf工具来剖析。
性能报告显示确实时stress占用了大量的CPU,通过修复权限问题来优化办理即可。

系统中涌现大量不可中断进程和僵尸进程怎么办?

进程状态

R Running/Runnable,表示进程在CPU的就绪行列步队中,正在运行或者等待运行;D Disk Sleep,不可中断状态就寝,一样平常表示进程正在跟硬件交互,并且交互过程中不许可被其他进程中断;Z Zombie,僵尸进程,表示进程实际上已经结束,但是父进程还没有回收它的资源;S Interruptible Sleep,可中断就寝状态,表示进程由于等待某个事宜而被系统挂起,当等待事宜发生则会被唤醒并进入R状态;I Idle,空闲状态,用在不可中断就寝的内核线程上。
该状态不会导致均匀负载升高;T Stop/Traced,表示进程处于停息或跟踪状态(SIGSTOP/SIGCONT, GDB调试);X Dead,进程已经消亡,不会在top/ps中看到。

对付不可中断状态,一样平常都是在很短韶光内结束,可忽略。
但是如果系统或硬件发生故障,进程可能会保持不可中断状态良久,乃至系统中涌现大量不可中断状态,此时需把稳是否涌现了I/O性能问题。

僵尸进程一样平常多进程运用随意马虎碰着,父进程来不及处理子进程状态时子进程就提前退出,此时子进程就变成了僵尸进程。
大量的僵尸进程会用尽PID进程号,导致新进程无法建立。

磁盘O_DIRECT问题

sudo docker run --privileged --name=app -itd feisky/app:iowaitps aux | grep '/app'

可以看到此时有多个app进程运行,状态分别时Ss+和D+。
个中后面s表示进程是一个会话的领导进程,+号表示前台进程组。

个中进程组表示一组相互关联的进程,子进程是父进程所在组的组员。
会话指共享同一个掌握终真个一个或多个进程组。

用top查看系统资源创造:1)均匀负载在逐渐增加,且1分钟内均匀负载达到了CPU个数,解释系统可能已经有了性能瓶颈;2)僵尸进程比较多且在一直增加;3)us和sys CPU利用率都不高,iowait却比较高;4)每个进程CPU利用率也不高,但有两个进程处于D状态,可能在等待IO。

剖析目前数据可知:iowait过高导致系统均匀负载升高,僵尸进程不断增长解释有程序没能精确清理子进程资源。

用dstat来剖析,由于它可以同时查看CPU和I/O两种资源的利用情形,便于比拟剖析。

dstat 1 10 #间隔1秒输出10组数据

可以看到当wai(iowait)升高时磁盘要求read都会很大,解释iowait的升高和磁盘的读要求有关。
接下来剖析到底时哪个进程在读磁盘。

之前 Top 查看的处于 D 状态的进程号,用 pidstat -d -p XXX 展示进程的 I/O 统计数据。
创造处于 D 状态的进程都没有任何读写操作。
在用 pidstat -d 查看所有进程的 I/O统计数据,看到 app 进程在进行磁盘读操作,每秒读取 32MB 的数据。
进程访问磁盘必须利用系统调用处于内核态,接下来重点便是找到app进程的系统调用。

sudo strace -p XXX #对app进程调用进行跟踪

报错没有权限,由于已经时 root 权限了。
以是碰着这种情形,首先要检讨进程状态是否正常。
ps 命令查找该进程已经处于Z状态,即僵尸进程。

这种情形下top pidstat之类的工具无法给出更多的信息,此时像第5篇一样,用 perf record -d和 perf report 进行剖析,查看app进程调用栈。

看到 app 确实在通过系统调用 sys_read() 读取数据,并且从 new_sync_read和 blkdev_direct_IO看出进程时进行直接读操作,要求直接从磁盘读,没有通过缓存导致iowait升高。

通过层层剖析后,root cause 是 app 内部进行了磁盘的直接I/O。
然后定位到详细代码位置进行优化即可。

僵尸进程

上述优化后 iowait 显著低落,但是僵尸进程数量仍旧在增加。
首先要定位僵尸进程的父进程,通过pstree -aps XXX,打印出该僵尸进程的调用树,创造父进程便是app进程。

查看app代码,看看子进程结束的处理是否精确(是否调用wait()/waitpid(),有没有注册SIGCHILD旗子暗记的处理函数等)。

碰到iowait升高时,先用dstat pidstat等工具确认是否存在磁盘I/O问题,再找是哪些进程导致I/O,不能用strace直接剖析进程调用时可以通过perf工具剖析。

对付僵尸问题,用pstree找到父进程,然后看源码检讨子进程结束的处理逻辑即可。

CPU性能指标CPU利用率用户CPU利用率, 包括用户态(user)和低优先级用户态(nice). 该指标过高解释运用程序比较繁忙.系统CPU利用率, CPU在内核态运行的韶光百分比(不含中断). 该指标高解释内核比较繁忙.等待I/O的CPU利用率, iowait, 该指标高解释系统与硬件设备I/O交互韶光比较长.软/硬中断CPU利用率, 该指标高解释系统中发生大量中断.steal CPU / guest CPU, 表示虚拟机占用的CPU百分比.均匀负载空想情形下均匀负载即是逻辑CPU个数,表示每个CPU都被充分利用. 若大于则解释系统负载较重.进程高下文切换包括无法获取资源的志愿切换和系统逼迫调度时的非志愿切换. 高下文切换本身是担保Linux正常运行的一项核心功能. 过多的切换则会将原来运行进程的CPU韶光花费在寄存器,内核占及虚拟内存等数据保存和规复上CPU缓存命中率CPU缓存的复用情形,命中率越高性能越好. 个中L1/L2常用在单核,L3则用在多核中性能工具均匀负载案例先用uptime查看系统均匀负载判断负载在升高后再用mpstat和pidstat分别查看每个CPU和每个进程CPU利用情形.找出导致均匀负载较高的进程.高下文切换案例先用vmstat查看系统高下文切换和中断次数再用pidstat不雅观察进程的志愿和非志愿高下文切换情形末了通过pidstat不雅观察线程的高下文切换情形进程CPU利用率高案例先用top查看系统和进程的CPU利用情形,定位到进程再用perf top不雅观察进程调用链,定位到详细函数系统CPU利用率高案例先用top查看系统和进程的CPU利用情形,top/pidstat都无法找到CPU利用率高的进程重新核阅top输出从CPU利用率不高,但是处于Running状态的进程入手perf record/report创造短时进程导致 (execsnoop工具)不可中断和僵尸进程案例先用top不雅观察iowait升高,创造大量不可中断和僵尸进程strace无法跟踪进程系统调用perf剖析调用链创造根源来自磁盘直接I/O软中断案例top不雅观察系统软中断CPU利用率高查看/proc/softirqs找到变革速率较快的几种软中断sar命令创造是网络小包问题tcpdump找出网络帧的类型和来源,确定SYN FLOOD攻击导致

根据不同的性能指标来找得当的工具:

先运行几个支持指标较多的工具,如 top/vmstat/pidstat,根据它们的输出可以得出是哪种类型的性能问题。
定位到进程后再用 strace/perf 剖析调用情形进一步剖析。
如果是软中断导致用 /proc/softirqs

CPU优化运用程序优化编译器优化:编译阶段开启优化选项,如gcc -O2算法优化异步处理:避免程序由于等待某个资源而一贯壅塞,提升程序的并发处理能力。
(将轮询更换为事宜关照)多线程代替多进程:减少高下文切换本钱善用缓存:加快程序处理速率系统优化CPU绑定:将进程绑定要1个/多个CPU上,提高CPU缓存命中率,减少CPU调度带来的高下文切换CPU独占:CPU亲和性机制来分配进程优先级调度:利用nice适当降落非核心运用的优先级为进程设置资源显示: cgroups设置利用上限,防止由某个运用自身问题耗尽系统资源NUMA优化: CPU尽可能访问本地内存中断负载均衡: irpbalance,将中断处理过程自动负载均衡到各个CPU上TPS、QPS、系统吞吐量的差异和理解QPS(TPS)并发数相应韶光QPS(TPS)=并发数/均匀相应韶光用户要求做事器做事器内部处理做事器返回给客户QPS 类似 TPS,但是对付一个页面的访问形成一个 TPS,但是一次页面要求可能包含多次对做事器的要求,可能计入多次 QPSQPS(Queries Per Second)每秒查询率,一台做事器每秒能够相应的查询次数.TPS(Transactions Per Second)每秒事务数,软件测试的结果.系统吞吐量,包括几个主要参数:QPS(TPS)并发数相应韶光QPS(TPS)=并发数/均匀相应韶光内存Linux内存是怎么事情的内存映射

大多数打算机用的主存都是动态随机访问内存(DRAM),只有内核才可以直接访问物理内存。
Linux内核给每个进程供应了一个独立的虚拟地址空间,并且这个地址空间是连续的。
这样进程就可以很方便的访问内存(虚拟内存)。

虚拟地址空间的内部分为内核空间和用户空间两部分,不同字长的处理器地址空间的范围不同。
32位系统内核空间占用1G,用户空间占3G。
64位系统内核空间和用户空间都是128T,分别占内存空间的最高和最低处,中间部分为未定义。

并不是所有的虚拟内存都会分配物理内存,只有实际利用的才会。
分配后的物理内存通过内存映射管理。
为了完成内存映射,内核为每个进程都掩护了一个页表,记录虚拟地址和物理地址的映射关系。
页表示实存储在CPU的内存管理单元MMU中,处理器可以直接通过硬件找出要访问的内存。

当进程访问的虚拟地址在页表中查不到时,系统会产生一个缺页非常,进入内核空间分配物理内存,更新进程页表,再返回用户空间规复进程的运行。

MMU以页为单位管理内存,页大小4KB。
为理解决页表项过多问题Linux供应了多级页表和HugePage的机制。

虚拟内存空间分布

用户空间内存从低到高是五种不同的内存段:

只读段 代码和常量等数据段 全局变量等堆 动态分配的内存,从低地址开始向上增长文件映射 动态库、共享内存等,从高地址开始向下增长栈 包括局部变量和函数调用的高下文等,栈的大小是固定的。
一样平常8MB内存分配与回收

分配

malloc 对应到系统调用上有两种实现办法:

brk() 针对小块内存(<128K),通过移动堆顶位置来分配。
内存开释后不立即归还内存,而是被缓存起来。
mmap()针对大块内存(>128K),直接用内存映射来分配,即在文件映射段找一块空闲内存分配。

前者的缓存可以减少缺页非常的发生,提高内存访问效率。
但是由于内存没有归还系统,在内存事情繁忙时,频繁的内存分配/开释会造成内存碎片。

后者在开释时直接归还系统,以是每次mmap都会发生缺页非常。

在内存事情繁忙时,频繁内存分配会导致大量缺页非常,使内核管理包袱增加。

上述两种调用并没有真正分配内存,这些内存只有在首次访问时,才通过缺页非常进入内核中,由内核来分配。

回收

内存紧张时,系统通过以下办法来回收内存:

回收缓存:LRU算法回收最近最少利用的内存页面;回收不常访问内存:把不常用的内存通过交流分区写入磁盘杀去世进程:OOM内核保护机制(进程花费内存越大 oom_score 越大,占用 CPU 越多 oom_score 越小,可以通过 /proc 手动调度 oom_adj)

echo -16 > /proc/$(pidof XXX)/oom_adj

如何查看内存利用情形

free来查看全体系统的内存利用情形

top/ps来查看某个进程的内存利用情形

VIRT 进程的虚拟内存大小RES 常驻内存的大小,即进程实际利用的物理内存大小,不包括swap和共享内存SHR 共享内存大小,与其他进程共享的内存,加载的动态链接库以及程序代码段%MEM 进程利用物理内存占系统总内存的百分比

若何理解内存中的Buffer和Cache?

buffer是对磁盘数据的缓存,cache是对文件数据的缓存,它们既会用在读要求也会用在写要求中

如何利用系统缓存优化程序的运行效率

缓存命中率

缓存命中率是指直接通过缓存获取数据的要求次数,占所有要求次数的百分比。
命中率越高解释缓存带来的收益越高,运用程序的性能也就越好。

安装bcc包后可以通过cachestat和cachetop来监测缓存的读写命中情形。

安装pcstat后可以查看文件在内存中的缓存大小以及缓存比例

#首先安装Goexport GOPATH=~/goexport PATH=~/go/bin:$PATHgo get golang.org/x/sys/unixgo ge github.com/tobert/pcstat/pcstat

dd缓存加速

dd if=/dev/sda1 of=file bs=1M count=512 #生产一个512MB的临时文件echo 3 > /proc/sys/vm/drop_caches #清理缓存pcstat file #确定刚才天生文件不在系统缓存中,此时cached和percent都是0cachetop 5dd if=file of=/dev/null bs=1M #测试文件读取速率#此时文件读取性能为30+MB/s,查看cachetop结果创造并不是所有的读都落在磁盘上,读缓存命中率只有50%。
dd if=file of=/dev/null bs=1M #重复上述读文件测试#此时文件读取性能为4+GB/s,读缓存命中率为100%pcstat file #查看文件file的缓存情形,100%全部缓存

O_DIRECT选项绕过系统缓存

cachetop 5sudo docker run --privileged --name=app -itd feisky/app:io-directsudo docker logs app #确认案例启动成功#实验结果表明每读32MB数据都要花0.9s,且cachetop输出中显示1024次缓存全部命中

但是凭觉得可知如果缓存命中读速率不应如此慢,读次数时1024,页大小为4K,五秒的韶光内读取了10244KB数据,即每秒0.8MB,和结果中32MB相差较大。
解释该案例没有充分利用缓存,疑惑系统调用设置了直接I/O标志绕过系统缓存。
因此接下来不雅观察系统调用。

strace -p $(pgrep app)#strace 结果可以看到openat打开磁盘分区/dev/sdb1,传入参数为O_RDONLY|O_DIRECT

这就阐明了为什么读32MB数据那么慢,直接从磁盘读写肯定远远慢于缓存。
找出问题后我们再看案例的源代码创造flags中指定了直接IO标志。
删除该选项后重跑,验证性能变革。

内存泄露,如何定位和处理?

对运用程序来说,动态内存的分配和回收是核心又繁芜的一个逻辑功能模块。
管理内存的过程中会发生各种各样的“事件”:

没精确回收分配的内存,导致了泄露访问的是已分配内存边界外的地址,导致程序非常退出

内存的分配与回收

虚拟内存分布从低到高分别是只读段,数据段,堆,内存映射段,栈五部分。
个中会导致内存泄露的是:

堆:由运用程序自己来分配和管理,除非程序退出这些堆内存不会被系统自动开释。
内存映射段:包括动态链接库和共享内存,个中共享内存由程序自动分配和管理

内存泄露的危害比较大,这些忘却开释的内存,不仅运用程序自己不能访问,系统也不能把它们再次分配给其他运用。
内存泄露不断累积乃至会耗尽系统内存。

如何检测内存泄露

预先安装systat,docker,bcc

sudo docker run --name=app -itd feisky/app:mem-leaksudo docker logs appvmstat 3

可以看到free在不断低落,buffer和cache基本保持不变。
解释系统的内存同等在升高。
但并不能解释存在内存泄露。
此时可以通过memleak工具来跟踪系统或进程的内存分配/开释要求

/usr/share/bcc/tools/memleak -a -p $(pidof app)

从 memleak 输出可以看到,运用在一直地分配内存,并且这些分配的地址并没有被回收。
通过调用栈看到是 fibonacci 函数分配的内存没有开释。
定位到源码后查看源码来修复增加内存开释函数即可。

为什么系统的 Swap 变高

系统内存资源紧张时通过内存回收和OOM杀去世进程来办理。
个中可回收内存包括:

缓存/缓冲区,属于可回收资源,在文件管理中常日叫做文件页在运用程序中通过fsync将脏页同步到磁盘交给系统,内核线程pdflush卖力这些脏页的刷新被运用程序修正过暂时没写入磁盘的数据(脏页),要先写入磁盘然后才能内存开释内存映射获取的文件映射页,也可以被开释掉,下次访问时从文件重新读取

对付程序自动分配的堆内存,也便是我们在内存管理中的匿名页,虽然这些内存不能直接开释,但是 Linux 供应了 Swap 机制将不常访问的内存写入到磁盘来开释内存,再次访问时从磁盘读取到内存即可。

Swap事理

Swap实质便是把一块磁盘空间或者一个本地文件当作内存来利用,包括换入和换出两个过程:

换出:将进程暂时不用的内存数据存储到磁盘中,并开释这些内存换入:进程再次访问内存时,将它们从磁盘读到内存中

Linux如何衡量内存资源是否紧张?

直接内存回收新的大块内存分配要求,但剩余内存不敷。
此时系统会回收一部分内存;kswapd0 内核线程定期回收内存。
为了衡量内存利用情形,定义了pages_min,pages_low,pages_high 三个阈值,并根据其来进行内存的回收操作。
剩余内存 < pages_min,进程可用内存耗尽了,只有内核才可以分配内存pages_min < 剩余内存 < pages_low,内存压力较大,kswapd0实行内存回收,直到剩余内存 > pages_highpages_low < 剩余内存 < pages_high,内存有一定压力,但可以知足新内存要求剩余内存 > pages_high,解释剩余内存较多,无内存压力pages_low = pages_min 5 / 4 pages_high = pages_min 3 / 2NUMA 与 SWAP

很多情形下系统剩余内存较多,但 SWAP 依旧升高,这是由于处理器的 NUMA 架构。

在NUMA架构下多个处理器划分到不同的 Node,每个Node都拥有自己确当地内存空间。
在剖析内存的利用时该当针对每个Node单独剖析

numactl --hardware #查看处理器在Node的分布情形,以及每个Node的内存利用情形

内存三个阈值可以通过 /proc/zoneinfo 来查看,该文件中还包括生动和非生动的匿名页/文件页数。

当某个Node内存不敷时,系统可以从其他Node探求空闲资源,也可以从本地内存中回收内存。
通过/proc/sys/vm/zone_raclaim_mode来调度。

0表示既可以从其他Node探求空闲资源,也可以从本地回收内存1,2,4 表示只回收本地内存,2表示可以会回脏数据回收内存,4表示可以用Swap办法回收内存。
swappiness

在实际回收过程中Linux根据 /proc/sys/vm/swapiness 选项来调度利用Swap的积极程度,从 0-100,数值越大越积极利用 Swap,即更方向于回收匿名页;数值越小越悲观利用 Swap,即更方向于回收文件页。

把稳:这只是调度 Swap 积极程度的权重,纵然设置为0,当剩余内存+文件页小于页高阈值时,还是会发生 Swap。

Swap升高时如何定位剖析

free #首先通过free查看swap利用情形,若swap=0表示未配置Swap#先创建并开启swapfallocate -l 8G /mnt/swapfilechmod 600 /mnt/swapfilemkswap /mnt/swapfileswapon /mnt/swapfilefree #再次实行free确保Swap配置成功dd if=/dev/sda1 of=/dev/null bs=1G count=2048 #仿照大文件读取sar -r -S 1 #查看内存各个指标变革 -r内存 -S swap#根据结果可以看出,%memused在不断增长,剩余内存kbmemfress不断减少,缓冲区kbbuffers不断增大,由此可知剩余内存不断分配给了缓冲区#一段韶光之后,剩余内存很小,而缓冲区占用了大部分内存。
此时Swap利用之间增大,缓冲区和剩余内存只在小范围颠簸停下sar命令cachetop5 #不雅观察缓存#可以看到dd进程读写只有50%的命中率,未命中数为4w+页,解释正式dd进程导致缓冲区利用升高watch -d grep -A 15 ‘Normal’ /proc/zoneinfo #不雅观察内存指标变革#创造升级内存在一个小范围一直的颠簸,低于页低阈值时会溘然增大到一个大于页高阈值的值

解释剩余内存和缓冲区的颠簸变革正是由于内存回收和缓存再次分配的循环往来来往。
有时候 Swap 用的多,有时候缓冲区颠簸更多。
此时查看 swappiness 值为60,是一个相对中和的配置,系统会根据实际运行情形来选去得当的回收类型。

如何“快准狠”找到系统内存存在的问题

内存性能指标

系统内存指标已用内存/剩余内存共享内存 (tmpfs实现)可用内存:包括剩余内存和可回收内存缓存:磁盘读取文件的页缓存,slab分配器中的可回收部分缓冲区:原始磁盘块的临时存储,缓存将要写入磁盘的数据

进程内存指标

虚拟内存:5大部分常驻内存:进程实际利用的物理内存,不包括Swap和共享内存共享内存:与其他进程共享的内存,以及动态链接库和程序的代码段Swap 内存:通过Swap换出到磁盘的内存

缺页非常

可以直接从物理内存等分配,次缺页非常须要磁盘 IO 参与(如 Swap),主缺页非常。
此时内存访问会慢很多内存性能工具

根据不同的性能指标来找得当的工具:

内存剖析工具包含的性能指标:

如何迅速剖析内存的性能瓶颈

常日先运行几个覆盖面比较大的性能工具,如 free,top,vmstat,pidstat 等

先用 free 和 top 查看系统整体内存利用情形再用 vmstat 和 pidstat,查看一段韶光的趋势,从而判断内请安题的类型最后进行详细剖析,比如内存分配剖析,缓存/缓冲区剖析,详细进程的内存利用剖析等

常见的优化思路:

最好禁止 Swap,若必须开启则只管即便降落 swappiness 的值减少内存的动态分配,如可以用内存池,HugePage 等只管即便利用缓存和缓冲区来访问数据。
如用堆栈明确声明内存空间来存储须要缓存的数据,或者用 Redis 外部缓存组件来优化数据的访问cgroups 等办法来限定进程的内存利用情形,确保系统内存不被非常进程耗尽/proc/pid/oom_adj 调度核心运用的 oom_score,担保纵然内存紧张核心运用也不会被OOM杀去世

vmstat 利用详解

vmstat 命令是最常见的 Linux/Unix 监控工具,可以展现给定时间间隔的做事器的状态值,包括做事器的 CPU 利用率,内存利用,虚拟内存交流情形,IO读写情形。
可以看到全体机器的 CPU,内存,IO 的利用情形,而不是单单看到各个进程的 CPU 利用率和内存利用率(利用场景不一样)。

vmstat 2procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 1379064 282244 11537528 0 0 3 104 0 0 3 0 97 0 0 0 0 0 1372716 282244 11537544 0 0 0 24 4893 8947 1 0 98 0 0 0 0 0 1373404 282248 11537544 0 0 0 96 5105 9278 2 0 98 0 0 0 0 0 1374168 282248 11537556 0 0 0 0 5001 9208 1 0 99 0 0 0 0 0 1376948 282248 11537564 0 0 0 80 5176 9388 2 0 98 0 0 0 0 0 1379356 282256 11537580 0 0 0 202 5474 9519 2 0 98 0 0 1 0 0 1368376 282256 11543696 0 0 0 0 5894 8940 12 0 88 0 0 1 0 0 1371936 282256 11539240 0 0 0 10554 6176 9481 14 1 85 1 0 1 0 0 1366184 282260 11542292 0 0 0 7456 6102 9983 7 1 91 0 0 1 0 0 1353040 282260 11556176 0 0 0 16924 7233 9578 18 1 80 1 0 0 0 0 1359432 282260 11549124 0 0 0 12576 5495 9271 7 0 92 1 0 0 0 0 1361744 282264 11549132 0 0 0 58 8606 15079 4 2 95 0 0 1 0 0 1367120 282264 11549140 0 0 0 2 5716 9205 8 0 92 0 0 0 0 0 1346580 282264 11562644 0 0 0 70 6416 9944 12 0 88 0 0 0 0 0 1359164 282264 11550108 0 0 0 2922 4941 8969 3 0 97 0 0 1 0 0 1353992 282264 11557044 0 0 0 0 6023 8917 15 0 84 0 0# 结果解释- r 表示运行行列步队(便是说多少个进程真的分配到CPU),我测试的做事器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会涌现CPU瓶颈了。
这个也和top的负载有关系,一样平常负载超过了3就比较高,超过了5就高,超过了10就不正常了,做事器的状态很危险。
top的负载类似每秒的运行行列步队。
如果运行行列步队过大,表示你的CPU很繁忙,一样平常会造成CPU利用率很高。
- b 表示壅塞的进程,这个不多说,进程壅塞,大家懂的。
- swpd 虚拟内存已利用的大小,如果大于0,表示你的机器物理内存不敷了,如果不是程序内存透露的缘故原由,那么你该升级内存了或者把耗内存的任务迁移到其他机器。
- free 空闲的物理内存的大小,我的机器内存统共8G,剩余3415M。
- buff Linux/Unix系统是用来存储,目录里面有什么内容,权限等的缓存,我本机大概占用300多M- cache cache直接用来影象我们打开的文件,给文件做缓冲,我本机大概占用300多M(这里是Linux/Unix的聪明之处,把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高 程序实行的性能,当程序利用内存时,buffer/cached会很快地被利用。
)- si 每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不足用或者内存透露了,要查找耗内存进程办理掉。
我的机器内存充裕,统统正常。
- so 每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上。
- bi 块设备每秒吸收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,以是一贯是0,但是我曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速率差不多140M每秒- bo 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。
bi和bo一样平常都要靠近0,不然便是IO过于频繁,须要调度。
- in 每秒CPU的中断次数,包括韶光中断- cs 每秒高下文切换次数,例如我们调用系统函数,就要进行高下文切换,线程的切换,也要进程高下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web做事器中,我们一样平常做性能测试时会进行几千并发乃至几万并发的测试,选择web做事器的进程可以由进程或者线程的峰值一贯下调,压测,直到cs到一个比较小的值,这个进程和线程数便是比较得当的值了。
系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致高下文切换,这个是很耗资源,也要只管即便避免频繁调用系统函数。
高下文切换次数过多表示你的CPU大部分摧残浪费蹂躏在高下文切换,导致CPU干正经事的韶光少了,CPU没有充分利用,是不可取的。
- us 用户CPU韶光,我曾经在一个做加密解密很频繁的做事器上,可以看到us靠近100,r运行行列步队达到80(机器在做压力测试,性能表现不佳)。
- sy 系统CPU韶光,如果太高,表示系统调用韶光长,例如是IO操作频繁。
- id 空闲CPU韶光,一样平常来说,id + us + sy = 100,一样平常我认为id是空闲CPU利用率,us是用户CPU利用率,sy是系统CPU利用率。
- wt 等待IO CPU韶光

pidstat 利用详解

pidstat 紧张用于监控全部或指定进程占用系统资源的情形,如CPU,内存、设备IO、任务切换、线程等。

利用方法:

pidstat –d interval times 统计各个进程的IO利用情形pidstat –u interval times 统计各个进程的CPU统计信息pidstat –r interval times 统计各个进程的内存利用信息pidstat -w interval times 统计各个进程的高下文切换p PID 指定PID

1、统计 IO 利用情形

pidstat -d 1 1003:02:02 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command03:02:03 PM 0 816 0.00 918.81 0.00 jbd2/vda1-803:02:03 PM 0 1007 0.00 3.96 0.00 AliYunDun03:02:03 PM 997 7326 0.00 1904.95 918.81 java03:02:03 PM 997 8539 0.00 3.96 0.00 java03:02:03 PM 0 16066 0.00 35.64 0.00 cmagent03:02:03 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command03:02:04 PM 0 816 0.00 1924.00 0.00 jbd2/vda1-803:02:04 PM 997 7326 0.00 11156.00 1888.00 java03:02:04 PM 997 8539 0.00 4.00 0.00 javaUIDPIDkB_rd/s:每秒进程从磁盘读取的数据量 KB 单位 read from disk each second KBkB_wr/s:每秒进程向磁盘写的数据量 KB 单位 write to disk each second KBkB_ccwr/s:每秒进程向磁盘写入,但是被取消的数据量,This may occur when the task truncates some dirty pagecache.iodelay:Block I/O delay,measured in clock ticksCommand:进程名 task name

2、统计 CPU 利用情形

# 统计CPUpidstat -u 1 1003:03:33 PM UID PID %usr %system %guest %CPU CPU Command03:03:34 PM 0 2321 3.96 0.00 0.00 3.96 0 ansible03:03:34 PM 0 7110 0.00 0.99 0.00 0.99 4 pidstat03:03:34 PM 997 8539 0.99 0.00 0.00 0.99 5 java03:03:34 PM 984 15517 0.99 0.00 0.00 0.99 5 java03:03:34 PM 0 24406 0.99 0.00 0.00 0.99 5 java03:03:34 PM 0 32158 3.96 0.00 0.00 3.96 2 ansibleUIDPID%usr: 进程在用户空间占用 cpu 的百分比%system: 进程在内核空间占用 CPU 百分比%guest: 进程在虚拟机占用 CPU 百分比%wait: 进程等待运行的百分比%CPU: 进程占用 CPU 百分比CPU: 处理进程的 CPU 编号Command: 进程名

3、统计内存利用情形

# 统计内存pidstat -r 1 10Average: UID PID minflt/s majflt/s VSZ RSS %MEM CommandAverage: 0 1 0.20 0.00 191256 3064 0.01 systemdAverage: 0 1007 1.30 0.00 143256 22720 0.07 AliYunDunAverage: 0 6642 0.10 0.00 6301904 107680 0.33 javaAverage: 997 7326 10.89 0.00 13468904 8395848 26.04 javaAverage: 0 7795 348.15 0.00 108376 1233 0.00 pidstatAverage: 997 8539 0.50 0.00 8242256 2062228 6.40 javaAverage: 987 9518 0.20 0.00 6300944 1242924 3.85 javaAverage: 0 10280 3.70 0.00 807372 8344 0.03 aliyun-serviceAverage: 984 15517 0.40 0.00 6386464 1464572 4.54 javaAverage: 0 16066 236.46 0.00 2678332 71020 0.22 cmagentAverage: 995 20955 0.30 0.00 6312520 1408040 4.37 javaAverage: 995 20956 0.20 0.00 6093764 1505028 4.67 javaAverage: 0 23936 0.10 0.00 5302416 110804 0.34 javaAverage: 0 24406 0.70 0.00 10211672 2361304 7.32 javaAverage: 0 26870 1.40 0.00 1470212 36084 0.11 promtailUIDPIDMinflt/s : 每秒次缺页缺点次数 (minor page faults),虚拟内存地址映射成物理内存地址产生的 page fault 次数Majflt/s : 每秒主缺页缺点次数 (major page faults), 虚拟内存地址映射成物理内存地址时,相应 page 在 swap 中VSZ virtual memory usage : 该进程利用的虚拟内存 KB 单位RSS : 该进程利用的物理内存 KB 单位%MEM : 内存利用率Command : 该进程的命令 task name

4、查看详细进程利用情形

pidstat -T ALL -r -p 20955 1 1003:12:16 PM UID PID minflt/s majflt/s VSZ RSS %MEM Command03:12:17 PM 995 20955 0.00 0.00 6312520 1408040 4.37 java03:12:16 PM UID PID minflt-nr majflt-nr Command03:12:17 PM 995 20955 0 0 java

内容来自twt社区,如侵删

标签:

相关文章