CPU、内存、IO过高分析

top命令

使用TOP命令查看CPU、内存使用状态
某进程cpu使用率 = 该进程cpu时间 / 总cpu时间。
在这里插入图片描述

img

第一行,任务队列信息,同 uptime 命令的执行结果

系统时间:07:27:05

运行时间:up 1:57 min,

当前登录用户: 3 user

负载均衡(uptime) load average: 0.00, 0.00, 0.00

​ average后面的三个数分别是1分钟、5分钟、15分钟的负载情况。

load average数据是每隔5秒钟检查一次活跃的进程数,然后按特定算法计算出的数值。如果这个数除以逻辑CPU的数量,结果高于5的时候就表明系统在超负荷运转了

第二行,Tasks — 任务(进程)

总进程:150 total, 运行:1 running, 休眠:149 sleeping, 停止: 0 stopped, 僵尸进程: 0 zombie

第三行,cpu状态信息 Cpu(s)表示的是 所有用户进程占用整个cpu的平均值

0.0%us【user space】— 用户空间占用CPU的百分比。

0.3%sy【sysctl】— 内核空间占用CPU的百分比。

0.0%ni【】— 改变过优先级的进程占用CPU的百分比

99.7%id【idolt】— 空闲CPU百分比

0.0%wa【wait】— IO等待占用CPU的百分比

0.0%hi【Hardware IRQ】— 硬中断占用CPU的百分比

0.0%si【Software Interrupts】— 软中断占用CPU的百分比

第四行,内存状态

1003020k total, 234464k used, 777824k free, 24084k buffers【缓存的内存量】

第五行,swap交换分区信息

2031612k total, 536k used, 2031076k free, 505864k cached【缓冲的交换区总量】

备注:

可用内存=free + buffer + cached

对于内存监控,在top里我们要时刻监控第五行swap交换分区的used,如果这个数值在不断的变化,说明内核在不断进行内存和swap的数据交换,这是真正的内存不够用了。

第四行中使用中的内存总量(used)指的是现在系统内核控制的内存数,

第四行中空闲内存总量(free)是内核还未纳入其管控范围的数量。

纳入内核管理的内存不见得都在使用中,还包括过去使用过的现在可以被重复利用的内存,内核并不把这些可被重新使用的内存交还到free中去,因此在linux上free内存会越来越少,但不用为此担心。

第六行,空行

第七行以下:各进程(任务)的状态监控

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(s)表示的是 所有用户进程占用整个cpu的平均值,由于每个核心占用的百分比不同,所以按平均值来算比较有参考意义。而%CPU显示的是进程占用一个核的百分比,而不是整个cpu(12核)的百分比,有时候可能大于100,那是因为该进程启用了多线程占用了多个核心,所以有时候我们看该值得时候会超过100%,但不会超过总核数*100。

vmstat

vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存、进程、CPU活动进行监控。是对系统的整体情况进行统计,不足之处是无法对某个进程进行深入分析。

vmstat 5 5 【在5秒时间内进行5次采样】

image

valgrind

Linux下可以用valgrind。

Valgrind包含下列工具:

​ 1、memcheck:检查程序中的内存问题,如泄漏、越界、非法指针等。

​ 2、callgrind:检测程序代码的运行时间和调用过程,以及分析程序性能。

​ 3、cachegrind:分析CPU的cache命中率、丢失率,用于进行代码优化。

​ 4、helgrind:用于检查多线程程序的竞态条件。

​ 5、massif:堆栈分析器,指示程序中使用了多少堆内存等信息。

CPU过高

  • 执行运算量大的任务。计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。计算密集型任务由于主要消耗CPU资源,因此,代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。
  • 共享资源竞争,死锁。比如IO等待、资源争用(同一资源被不同线程请求,而此资源又需要保持一致性,只能前一个释放后一个再访问,这样导致的等待)
  • CPU太差,主频太低
  • 死循环时,一直占用cpu
  • 大数据处理的情况下,代码采用了多次循环遍历的方式处理,很耗CPU.(mysql查询语句索引没有命中导致).
  • 过多的系统调用,系统调用即调用操作系统提供的程序接口,比如Java项目中写日志,会调用系统接口进行日志写操作,这样会导致系统CPU使用率过高
  • 系统中断和切换频繁很耗用CPU。过多的中断,中断是CPU用来响应请求的机制,比如键盘的输入,鼠标的点击等都会产生中断,中断是通知CPU有任务需要响应,CPU停下正在执行的程序来响应当前的中断

内存过高

  • 读写量大,磁盘太慢。例一次将内存缓存中的数据库刷到文件,导致CPU及内存的过高
  • 内存不足,程序分配的内存超出物理机的内存大小,导致无法继续分配内存,出现OOM报错。操作系统就会用虚拟内存,肯定要用系统的交换区了,比如LINUX 的SWAP,就造成分页增多。过多的页交换:内存不够用来存储需要的数据时,操作系统会把原内存中的部分内容释放掉(移除或者存入磁盘),然后把需要的内容载入,这个过程就是页交换。
  • 内存泄漏,出现无法释放的内存块或超出使用的内存块,久而久之,内存泄漏的对象堆积起来,也会导致物理机的内存被耗尽,出现OOM报错。
  • 数据存放时需要考虑对齐问题。在内存紧张或者涉及IPC的情况,一般强制对齐。对齐情况下,CPU寻址的速度会快很多

IO过多

  • 执行过多的io交互。IO密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(IO就是指把内容从硬盘上读到内存的过程,或者是从网络上接收信息到本机内存的过程】的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。

  • 大文件频繁读写的cpu开销远小于小文件频繁读写的开销。因为在I/O吞吐量一定时,小文件的读写更加频繁,需要更多的cpu来处理I/O的中断。另外一点是大文件之所以是大文件是对应到磁盘的LBA是连续的地址,而小文件对应到磁盘的LBA是多个不连续的LBA地址。这样的话需要磁头不断的去寻找所需的对应位置。无形中加大的寻道时间。

C/C++ CPU/内存过高占用分析与优化

一、cpu分析

1、死循环。在用C++进行多线程编程的时候,时常需要写一些类似于死循环的结构来执行代码,这些死循环如果没有经过处理一直开着,那么CPU的占用率就会居高不下的做着很多无用的操做。为解决这个问题我们可以通过在各线程中的适当位置添加Sleep函数来休眠该线程,使其少做这些无用的操作。经过这个处理,正常能压缩掉一半以上的CPU占用。

2、大数据处理的情况下,代码采用了多次循环遍历的方式处理,很耗CPU。(mysql查询语句索引没有命中导致或者复合查询过多)。

3、在使用一些系统函数或库函数时,也需要仔细阅读使用手册,避免出现大量的无效的内存申请、释放和重置操作。减少耗性能的函数的使用(memset、strncpy这个字符串操作函数是比较耗费性能的

4、程序中存在过多的加锁/解锁操作,是程序CPU性能恶化的另外一大类原因,其典型的现象是:系统态的CPU过高,甚至超过了用户态CPU。

5、程序的上下文切换过多,也会导致程序的性能恶化。当线程需要等待一定的条件时会被操作系统放入的休眠队列中,直到被唤醒。

6、I/O操作过多。I/O操作过多问题中最常见的一类是程序打印了过多的日志。

对于C/C++程序,目前业界使用的比较多的CPU热点定位工具有:valgrind中组件callgrind,gprof(GNU Profiler),google perf tools组件中的CPU Profiler和Oprofiler。

CPU 分析步骤:

第一步:使用top命令查看程序进程id

第二步:top -Hp pid 定位CPU占用过高的线程id

第三步: 在后台开发中,strace -p 能够很方便的查看系统调用的参数,返回值,耗时等信息。strace -p tid定位线程堆栈

shell> strace -cp <PID>

通过「c」选项用来汇总各个操作的总耗时。strace -cp

使用valgrind分析CPU:

valgrind --tool=callgrind  ./a.out

执行完上述命令后,在当前目录下生成 callgrind.out.文件,使用可视化kcachegrind查看

kcachegrind callgrind.out.21479

在这里插å¥å›¾ç‰‡æè¿°

二、内存泄漏分析

memcheck工具的使用方式如下:

valgrind --tool=memcheck ./a.out

从上面的命令可以清楚的看到, 主要的命令是valgrind,而我们想使用的工具是通过’-tool’选项来指定的. 上面的‘a.out’指的是我们想使用memcheck运行的可执行文件.

该工具可以检测下列与内存相关的问题 :

  • 未释放内存的使用
  • 对释放后内存的读/写
  • 对已分配内存块尾部的读/写
  • 内存泄露
  • 不匹配的使用malloc/new/new[] 和 free/delete/delete[]
  • 重复释放内存
$ valgrind --tool=memcheck ./val
==2862== Memcheck, a memory error detector
==2862== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2862== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2862== Command: ./val
==2862==
==2862== Use of uninitialised value of size 8
==2862==    at 0x400530: main (valgrind.c:8)
==2862==

[#]
==2862==
==2862== HEAP SUMMARY:
==2862==     in use at exit: 0 bytes in 0 blocks
==2862==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==2862==
==2862== All heap blocks were freed -- no leaks are possible
==2862==
==2862== For counts of detected and suppressed errors, rerun with: -v
==2862== Use --track-origins=yes to see where uninitialized values come from
==2862== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
  • definitely lost: 肯定的内存泄漏,这表示在程序退出时,有内存没有回收,但是也没有指针指向该内存。这种情况最为严重。
  • indirectly lost: 间接的内存泄漏,如类之中定义的指针指向的内存没有回收。这种情况和上述相同。
  • possibly lost: 可能出现内存泄漏。这种情况需要仔细排查,可能代码没有问题,也可能有异常的内存泄露。
  • still reachable: 程序没主动释放内存,在退出时候该内存仍能访问到。这种情况一般问题不大,因为程序退出之后操作系统会回收程序的内存,所以这种情况一般问题不大。

三、core分析

gdb调试

Golang 内存、cpu分析

参考链接1

参考链接2

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值