在做JVM内存分析前,需要堆JVM内存及垃圾回收算法和垃圾回收器有一定了解,具体可以参考我之前的一篇文章:常见的垃圾回收器及垃圾回收算法
我们在做开发的时候不可避免的会遇到一些问题,诸如下面这些问题:
做内存监控可以帮助我尽可能避免这些问题,做内存分析可以帮我们更快的定位问题所在,不论如何,结果都是我们要达到尽量减少问题、减少程序的相应时间、增加服务的处理速度和吞吐量,给用户带来更好的体验。
我们一直说调优调优,调优调的是什么?既然是调优我们是从JVM层面考虑,就不需要考虑代码层面诸如死锁之类的东西,那么具体怎么调优呢?我们可以按照以下步骤来:
我们要知道做JVM调优目的主要是防止出现和解决OOM、让JVM做出合理的GC。
调优的结果不一定是好的,所以我们可以根据一些信息去判断调优的结果:
调优的结果我们可以从以下几个方法去评价感知:
提交请求和返回该请求的响应之间使用的时间,一般比较关注平均响应时间。常用操作的响应时间列表:
操作 | 响应时间 |
打开一个站点 | 几秒 |
数据库查询一条记录(有索引) | 十几毫秒 |
机械磁盘一次寻址定位 | 4毫秒 |
从机械磁盘顺序读取1M数据 | 2毫秒 |
从SSD磁盘顺序读取1M数据 | 0.3毫秒 |
从远程分布式换成Redis 读取一个数据 | 0.5毫秒 |
从内存读取 1M数据 | 十几微妙 |
Java程序本地方法调用 | 几微妙 |
网络传输2Kb数据 | 1 微妙 |
top命令经常用来监控linux的系统状况,是常用的性能分析工具,能够实时显示系统中各个进程的资源占用情况。
top的使用方式 top [选项]
详细参数如下:
参数 | 说明 |
-b | 以批处理模式操作 |
-c | 显示完整的命令 |
-d | 屏幕刷新间隔时间,默认5秒 |
-I | 忽略失效过程 |
-s | 保密模式 |
-S | 累积模式 |
-i <时间> | 设置刷新间隔时间 |
-u <用户名> | 指定用户名 |
-p <进程号> | 指定进程 |
-n <次数> | 循环显示的次数 |
结果展示如下:
第一行 15:19:43 up 2 days, 23:17, 0 users, load average: 0.64, 0.62, 0.70
内容 | 含义 |
15:19:43 | 表示当前时间 |
up 2 days, 23:17 | 系统已运行时间 |
0 users | 当前登录用户数 |
load average: 0.64, 0.62, 0.70 | 系统负载,即任务队列的平均长度。 三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值。 |
需要注意的是: 如果load average这个数值除以逻辑CPU的数量,结果高于5的时候就表明系统在超负荷运转了。
第二行 Tasks: 34 total, 1 running, 33 sleeping, 0 stopped, 0 zombie
第三行 %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
内容 | 含义 |
34 total | 进程总数 |
1 running | 正在运行的进程数 |
33 sleeping | 睡眠的进程数 |
0 stopped | 停止的进程数 |
0 zombie | 僵尸进程数 |
0.0 us | 用户空间占用CPU百分比 |
0.0 sy | 内核空间占用CPU百分比 |
0.0 ni | 用户进程空间内改变过优先级的进程占用CPU百分比 |
99.9 id | 空闲CPU百分比 |
0.0 wa | 等待输入输出的CPU时间百分比 |
0.0 hi | 硬中断(Hardware IRQ)占用CPU的百分比 |
0.0 si | 软中断(Software Interrupts)占用CPU的百分比 |
0.0 st | 用于有虚拟cpu的情况,用来指示被虚拟机偷掉的cpu时间。 |
第四行 KiB Mem : 4194304 total, 793660 free, 2795212 used, 605432 buff/cache
第五行 KiB Swap: 0 total, 0 free, 0 used. 793660 avail Mem
内容 | 含义 |
4194304 total | 物理内存总量 |
793660 free | 空闲内存总量 |
2795212 used | 使用的物理内存总量 |
605432 buff/cache | 用作内核缓存的内存量 |
0 total | 交换区总量 |
0 free | 空闲交换区总量 |
0 used | 使用的交换区总量 |
793660 avail Mem | 代表可用于进程下一次分配的物理内存数量 |
列名 | 含义 |
PID | 进程id |
PPID | 父进程id |
RUSER | 用户名 |
UID | 进程所有者的用户id |
USER | 进程所有者的用户名 |
GROUP | 进程所有者的组名 |
TTY | 启动进程的终端名。不是从终端启动的进程则显示为 |
PR | 优先级 |
NI | nice值。负值表示高优先级,正值表示低优先级 |
P | 最后使用的CPU,仅在多CPU环境下有意义 |
%CPU | 上次更新到现在的CPU时间占用百分比 |
TIME | 进程使用的CPU时间总计,单位秒 |
TIME+ | 进程使用的CPU时间总计,单位1/100秒 |
%MEM | 进程使用的物理内存百分比 |
VIRT | 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES |
SWAP | 进程使用的虚拟内存中,被换出的大小,单位kb |
RES | 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA |
CODE | 可执行代码占用的物理内存大小,单位kb |
DATA | 可执行代码以外的部分(数据段+栈)占用的物理内存大小,单位kb |
SHR | 共享内存大小,单位kb |
nFLT | 页面错误次数 |
nDRT | 最后一次写入到现在,被修改过的页面数。 |
S | 进程状态。D=不可中断的睡眠状态 |
COMMAND | 命令名/命令行 |
WCHAN | 若该进程在睡眠,则显示睡眠中的系统函数名 |
Flags | 任务标志 |
在使用top命令查看linux的系统使用情况之后,我们可以在结果页面使用一些命令帮助我们更加方便的收集查看自己想要信息,具体命令如下:
参数 | 含义 |
数字1 | 监控每个逻辑CPU状况 |