来源:https://my.oschina.net/xiaolyuh/blog/4261951
内存瓶颈
free
free 是查看内存使用情况,包括物理内存、交换内存 (swap) 和内核缓冲区内存。
free -h -s 3 表示每隔三秒输出一次内存情况,命令如下- [1014154@cc69dd4c5-4tdb5 ~]$ free
- total used free shared buff/cache available
- Mem: 119623656 43052220 45611364 4313760 30960072 70574408
- Swap: 0 0 0
- [1014154@cc69dd4c5-4tdb5 ~]$ free -h -s 3
- total used free shared buff/cache available
- Mem: 114G 41G 43G 4.1G 29G 67G
- Swap: 0B 0B 0B
- total used free shared buff/cache available
- Mem: 114G 41G 43G 4.1G 29G 67G
- Swap: 0B 0B 0B
复制代码
- Mem:是内存的使用情况。
- Swap:是交换空间的使用情况。
- total: 系统总的可用物理内存和交换空间大小。
- used: 已经被使用的物理内存和交换空间。
- free: 还有多少物理内存和交换空间可用使用,是真正尚未被使用的物理内存数量。
- shared:被共享使用的物理内存大小。
- buff/cache:被 buffer(缓冲区) 和 cache(缓存) 使用的物理内存大小。
- available: 还可以被应用程序使用的物理内存大小,它是从应用程序的角度看到的可用内存数量,available ≈ free + buffer + cache。
交换空间 (swap space)
swap space 是磁盘上的一块区域,当系统物理内存吃紧时,Linux 会将内存中不常访问的数据保存到 swap 上,这样系统就有更多的物理内存为各个进程服务,而当系统需要访问 swap 上存储的内容时,再将 swap 上的数据加载到内存中,这就是常说的换出和换入。交换空间可以在一定程度上缓解内存不足的情况,但是它需要读写磁盘数据,所以性能不是很高。
vmstat(推荐)
vmstat(VirtualMeomoryStatistics,虚拟内存统计)是 Linux 中监控内存的常用工具,可对操作系统的虚拟内存、进程、CPU 等的整体情况进行监视,推荐使用。
vmstat 5 3 表示每隔 5 秒统计一次,一共统计三次。- [1014154@cc69dd4c5-4tdb5 ~]$ vmstat 5 3
- procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
- r b swpd free buff cache si so bi bo in cs us sy id wa st
- 8 0 0 45453212 374768 30763728 0 0 14 99 1 1 11 10 78 0 1
- 10 0 0 45489232 374768 30763360 0 0 2 1275 95118 97908 13 11 75 0 1
- 6 0 0 45452908 374768 30765148 0 0 0 3996 89924 92073 12 10 78 0 1
复制代码 procs
r:表示运行和等待 CPU 时间片的进程数(就是说多少个进程真的分配到 CPU),这个值如果长期大于系统 CPU 个数,说明 CPU 不足,需要增加 CPU。 b:表示在等待资源的进程数,比如正在等待 I/O 或者内存交换等。
memory
swpd:表示切换到内存交换区的内存大小,即虚拟内存已使用的大小(单位 KB),如果大于 0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。 free:表示当前空闲的物理内存。 buff:表示缓冲大小,一般对块设备的读写才需要缓冲 Cache:表示缓存大小,一般作为文件系统进行缓冲,频繁访问的文件都会被缓存,如果 cache 值非常大说明缓存文件比较多,如果此时 io 中的 bi 比较小,说明文件系统效率比较好。
swap
si:表示数据由磁盘读入内存;通俗的讲就是每秒从磁盘读入虚拟内存的大小,如果这个值大于 0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。 so:表示由内存写入磁盘,也就是由内存交换区进入内存的数据大小。
注意:一般情况下 si、so 的值都为 0,如果 si、so 的值长期不为 0,则说明系统内存不足,需要增加系统内存
io
bi:表示由块设备读入数据的总量,即读磁盘,单位 kb/s bo:表示写到块设备数据的总量,即写磁盘,单位 kb/s
注意:如果 bi+bo 的值过大,且 wa 值较大,则表示系统磁盘 IO 瓶颈。
system
in:表示某一时间间隔内观测到的每秒设备终端数。 cs:表示每秒产生的上下文切换次数,这个值要越小越好,太大了,要考虑调低线程或者进程的数目。例如在 apache 和 nginx 这种 web 服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择 web 服务器的进程可以由进程或者线程的峰值一直下调,压测,直到 cs 到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的 CPU 大部分浪费在上下文切换,导致 CPU 干正经事的时间少了,CPU 没有充分利用,是不可取的。
注意:这两个值越大,则由内核消耗的 CPU 就越多。
CPU
us:表示用户进程消耗的 CPU 时间百分比,us 值越高,说明用户进程消耗 CPU 时间越多,如果长期大于 50%,则需要考虑优化程序或者算法。 sy:表示系统内核进程消耗的 CPU 时间百分比,一般来说 us+sy 应该小于 80%,如果大于 80%,说明可能存在 CPU 瓶颈。 id:表示 CPU 处在空间状态的时间百分比。 wa:表示 IP 等待所占用的 CPU 时间百分比,wa 值越高,说明 I/O 等待越严重,根据经验 wa 的参考值为 20%,如果超过 20%,说明 I/O 等待严重,引起 I/O 等待的原因可能是磁盘大量随机读写造成的,也可能是磁盘或者监控器的贷款瓶颈(主要是块操作)造成的。
sar
sar 和 free 类似 sar -r 3 每隔三秒输出一次内存信息:- [root@localhost ~]# sar -r 3
- Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain) 2020年04月28日 _x86_64_ (2 CPU)
- 15时40分10秒 kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
- 15时40分13秒 106800 1314960 92.49 2144 573248 4110864 116.82 563664 498888 36
- 15时40分16秒 106816 1314944 92.49 2144 573248 4110864 116.82 563668 498888 36
- 15时40分19秒 106816 1314944 92.49 2144 573248 4110864 116.82 563668 498888 36
复制代码 CPU 瓶颈
查看机器 cpu 核数
- CPU总核数 = 物理CPU个数 * 每颗物理CPU的核数
- 总逻辑CPU数 = 物理CPU个数 * 每颗物理CPU的核数 * 超线程数
复制代码 查看 CPU 信息(型号)
- [1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
- 32 Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz
复制代码 查看物理 CPU 个数
- [1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
- 16
复制代码 查看每个物理 CPU 中 core 的个数 (即核数)
- [1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo| grep "cpu cores"| uniq
- cpu cores : 2
复制代码 查看逻辑 CPU 的个数
- [1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo| grep "processor"| wc -l
- 32
复制代码 top
在 Linux 内核的操作系统中,进程是根据虚拟运行时间(由进程优先级、nice 值加上实际占用的 CPU 时间进行动态计算得出)进行动态调度的。在执行进程时,需要从用户态转换到内核态,用户空间不能直接操作内核空间的函数。通常要利用系统调用来完成进程调度,而用户空间到内核空间的转换通常是通过软中断来完成的。例如要进行磁盘操作,用户态需要通过系统调用内核的磁盘操作指令,所以 CPU 消耗的时间被切分成用户态 CPU 消耗、系统(内核) CPU 消耗,以及磁盘操作 CPU 消耗。执行进程时,需要经过一系列的操作,进程首先在用户态执行,在执行过程中会进行进程优先级的调整(nice),通过系统调用到内核,再通过内核调用,硬中断、软中断,让硬件执行任务。执行完成之后,再从内核态返回给系统调用,最后系统调用将结果返回给用户态的进程。
top 可以查看 CPU 总体消耗,包括分项消耗,如 User,System,Idle,nice 等。Shift + H 显示 java 线程;Shift + M 按照内存使用排序;Shift + P 按照 CPU 使用时间(使用率)排序;Shift + T 按照 CPU 累积使用时间排序;多核 CPU,进入 top 视图 1,可以看到各各 CPU 的负载情况。- top - 15:24:11 up 8 days, 7:52, 1 user, load average: 5.73, 6.85, 7.33
- Tasks: 17 total, 1 running, 16 sleeping, 0 stopped, 0 zombie
- %Cpu(s): 13.9 us, 9.2 sy, 0.0 ni, 76.1 id, 0.1 wa, 0.0 hi, 0.1 si, 0.7 st
- KiB Mem : 11962365+total, 50086832 free, 38312808 used, 31224016 buff/cache
- KiB Swap: 0 total, 0 free, 0 used. 75402760 avail Mem
- PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
- 300 ymmapp 20 0 17.242g 1.234g 14732 S 2.3 1.1 9:40.38 java
- 1 root 20 0 15376 1988 1392 S 0.0 0.0 0:00.06 sh
- 11 root 20 0 120660 11416 1132 S 0.0 0.0 0:04.94 python
- 54 root 20 0 85328 2240 1652 S 0.0 0.0 0:00.00 su
- 55 ymmapp 20 0 17432 1808 1232 S 0.0 0.0 0:00.00 bash
- 56 ymmapp 20 0 17556 2156 1460 S 0.0 0.0 0:00.03 control.sh
- 57 ymmapp 20 0 11880 740 576 S 0.0 0.0 0:00.00 tee
- 115 ymmapp 20 0 17556 2112 1464 S 0.0 0.0 0:00.02 control_new_war
- 133 root 20 0 106032 4240 3160 S 0.0 0.0 0:00.03 sshd
- 134 ymmapp 20 0 17080 6872 3180 S 0.0 0.0 0:01.82 ops-updater
- 147 ymmapp 20 0 17956 2636 1544 S 0.0 0.0 0:00.07 control.sh
- 6538 ymmapp 20 0 115656 10532 3408 S 0.0 0.0 0:00.46 beidou-agent
- 6785 ymmapp 20 0 2572996 22512 2788 S 0.0 0.0 0:03.44 gatherinfo4dock
- 29241 root 20 0 142148 5712 4340 S 0.0 0.0 0:00.04 sshd
- 29243 1014154 20 0 142148 2296 924 S 0.0 0.0 0:00.00 sshd
- 29244 1014154 20 0 15208 2020 1640 S 0.0 0.0 0:00.00 bash
- 32641 1014154 20 0 57364 2020 1480 R 0.0 0.0 0:00.00 top
复制代码 第一行:15:24:11 up 8 days, 7:52, 1 user, load average: 5.73, 6.85, 7.33: 15:24:11 系统时间,up 8 days 运行时间,1 user 当前登录用户数,load average 负载均衡情况,分别表示 1 分钟,5 分钟,15 分钟负载情况。
第二行:Tasks: 17 total, 1 running, 16 sleeping, 0 stopped, 0 zombie: 总进程数 17,运行数 1,休眠 16,停止 0,僵尸进程 0。
第三行:%Cpu(s): 13.9 us, 9.2 sy, 0.0 ni, 76.1 id, 0.1 wa, 0.0 hi, 0.1 si, 0.7 st: 用户空间 CPU 占比 13.9%,内核空间 CPU 占比 9.2%,改变过优先级的进程 CPU 占比 0%,空闲 CPU 占比 76.1,IO 等待占用 CPU 占比 0.1%,硬中断占用 CPU 占比 0%,软中断占用 CPU 占比 0.1%, 当前 VM 中的 cpu 时钟被虚拟化偷走的比例 0.7%。
第四和第五行表示内存和 swap 区域的使用情况。
第七行表示:
- PID: 进程 id
- USER: 进程所有者
- PR: 进程优先级
- NI:nice 值。负值表示高优先级,正值表示低优先级
- VIRT: 虚拟内存,进程使用的虚拟内存总量,单位 kb。VIRT=SWAP+RES
- RES: 常驻内存,进程使用的、未被换出的物理内存大小,单位 kb。RES=CODE+DATA
- SHR: 共享内存,共享内存大小,单位 kb
- S: 进程状态。D = 不可中断的睡眠状态 R = 运行 S = 睡眠 T = 跟踪 / 停止 Z = 僵尸进程
- %CPU: 上次更新到现在的 CPU 时间占用百分比
- %MEM : 进程使用的物理内存百分比
- TIME+ : 进程使用的 CPU 时间总计,单位 1/100 秒
- COMMAND : 进程名称(命令名 / 命令行)
计算在 cpu load 里面的 uninterruptedsleep 的任务数量
[code]top -b -n 1 | awk '{if (NR 目录地址[/td][td]对 apache 或者 nginx 访问 log 进行响应时间排序,$12 表示 cookie log 中的 12 列表示响应时间 用于排查是否是由于是某些访问超长造成整体的 RT 变长[/td][td][/td][/tr][tr][td][/td][td]grep -v 'HTTP/1.1" 200'[/td][td]取出非 200 响应码的 URL[/td][td][/td][/tr][tr][td][/td][td]pgm -A -f $ 应用集群名称 "grep"'301' log 文件地址 | wc -l"[/td][td]查看整个集群的 log 中 301 状态码的数量[/td][td][/td][/tr][tr][td][/td][td]ps -efL | grep [PID] | wc -l[/td][td]查看某个进程创建的线程数[/td][td][/td][/tr][tr][td][/td][td]find / -type f -name "*.log" | xargs grep "ERROR"[/td][td]统计所有的 log 文件中,包含 Error 字符的行[/td][td]这个在排查问题过程中比较有用[/td][/tr][tr][td][/td][td]jstat -gc [pid][/td][td]查看 gc 情况[/td][td][/td][/tr][tr][td][/td][td]jstat -gcnew [pid][/td][td]查看 young 区的内存使用情况,包括 MTT (最大交互次数就被交换到 old 区),TT 是目前已经交换的次数[/td][td][/td][/tr][tr][td][/td][td]jstat -gcold[/td][td]查看 old 区的内存使用情况[/td][td][/td][/tr][tr][td][/td][td]jmap -J-d64 -dump:format=b,file=dump.bin PID[/td][td]dump 出内存快照[/td][td]-J-d64 防止 jmap 导致虚拟机 crash (jdk6 有 bug)[/td][/tr][tr][td][/td][td]-XX:+HeapDumpOnOutOfMemeryError[/td][td]在 java 启动时加入,当出现内存溢出时,存储内存快照[/td][td][/td][/tr][tr][td][/td][td]jmap -histo [pid][/td][td]按照对象内存大小排序[/td][td]注意会导致 full gc[/td][/tr][tr][td][/td][td]gcore [pid][/td][td]导出完成的内存快照[/td][td]通常和 jmap -permstat /opt/**/java gcore.bin 一起使用,将 core dump 转换成 heap dump[/td][/tr][tr][td][/td][td]-XX:HeapDumpPath=/home/logs -Xloggc:/home/log/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps[/td][td]在 Java 启动参数中加入,打印 gc 日志[/td][td][/td][/tr][tr][td][/td][td]-server -Xms4000m -Xmx4000m -Xmn1500m -Xss256k -XX:PermSize=340m -XX:MaxPermSize=340m -XX:+UseConcMarkSweepGC[/td][td]调整 JVM 堆大小[/td][td]xss 是栈大小[/td][/tr][/table]近期热文推荐:
1.1,000+ 道 Java面试题及答案整理(2022最新版)
2.劲爆!Java 协程要来了。。。
3.Spring Boot 2.x 教程,太全了!
4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!
5.《Java开发手册(嵩山版)》最新发布,速速下载!
觉得不错,别忘了随手点赞+转发哦!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |