文章目标
当Java项目出现性能瓶颈的时候,通常先是对资源消耗做分析,包括CPU,文件IO,网络IO,内存;之后再结合相应工具查找消耗主体的程序代码。本文主要介绍系统资源消耗的分析过程,以及常用的Java线程分析方法。
CPU分析
在Linux中,CPU主要用于处理中断、内核及用户任务,优先级为:中断>内核>用户。在分析CPU消耗状况的时候,需要了解以下三个概念。
上下文切换
每个CPU(或多核CPU的每个核心)在同一时间只能执行一个线程<不包括超线程CPU>,Linux采用抢占式调度。当线程执行到达一个时间片后,如果线程有IO阻塞或高优先级线程要执行的时候,Linux将执行线程切换,切换前先保存当前线程执行状态(现场),并恢复待执行线程状态,这个过程就叫做上下文切换。在Java应用中,文件IO、网络IO、锁等待、线程Sleep操作都会使该线程进行阻塞或睡眠状态,从而触发上下文切换。频繁的上下文切换会造成内核占用较高的CPU,使得响应速度下降。
运行队列
每个CPU核心都维护了一个可运行队列,例如一个4核CPU,启动8个线程,且8个线程都处于可运行状态,平均分配情况下,每个核心的可运行队列里就有2个线程。通常而言,系统的load是由CPU运行队列决定的,假设以上状态维持了1分钟,则1分钟内系统load就是2。运行队列值越大,代表线程要消耗越长的时间才能执行完成。通常建议每个核心运行队列为1-3个。
利用率
CPU利用率指在用户进程,内核,中断处理,IO等待以及空闲五个部分百分比,这五个值是用来分析CPU消耗情况的关键指标。Linux System and NetWork Performent Monitoring建议用户进程/内核消耗比例为 65%-70% / 30%-35% 左右。
常用top, pidstat, sar, vmstat 1 分析占用情况,下图是top示例
us:用户进程处理占用百分比
sy:内核线程处理占用百分比
ni:被nice命令改变优先级的任务所占百分比
id:cpu空闲时间占用百分比
wa:在执行过程中等待IO所占百分比
hi:硬件中断占用百分比
si:软件中断占用百分比
st:虚拟机偷取时间百分比
对Java应用而言,线程消耗主要体现在us, sy上:
us: 用户进程处理占用百分比
us占用分析,需要依靠相关命令找出主体消耗线程ID(tid),然后转化成十六进制(printf "%x\n" tid),再用 kill -3 java_pid或 jstack -l java_pid 命令dump出线程信息,通过之前的十六进制值在dump信息中找到nid相等的线程,即为消耗CPU的线程。采样的时候要多做几次,保证找到的是真实的消耗线程。
在Java应用中如果us占用过高,代表运行的应用程序消耗了大部分CPU,常见为线程一直处理可运行状态(Runnable),并且无阻塞地执行循环,正则或复杂计算;也可能是每次请求都分配大量内存,导致频繁GC甚至频繁FullGC造成的,这时就需要依靠jvm工具查看了(jps, jmap, jstat等) 。
sy: 内核线程处理占用百分比
sy值过高表示Linux花费大量时间在线程切换上,Java造成原因通常是启动大量线程,且多数线程处理不断阻塞(如IO等待,锁等待)和执行的状态变化中,造成大量上下文切换。这时可通过 kill -3 java_pid或jstack -l java_pid 命令dump出线程信息,找出不断切换线程执行状态的原因(也可以通过TDA分析)。
如下使用 vmstat 1 查看上下文切换(cs)及sy占用
如果cs值很高的话,再使用 jstack -l java_pid 查看线程堆栈信息,通常可以发现大量线程处于TIMED_WAITING (on object monitor)与Runnable状态转化中,通过on object monitor可以找到锁竞争激烈的代码,从而找出上下文切换的原因。
文件IO分析
Linux在操作文件的时候,会将文件放入文件缓存区,直到内存不够或系统要释放内存给用户进程使用时,才会交换出去。因此在查看内存状态时经常发现可用(free)的物理内存不足,但cached用了很多,这是Linux提升文件IO速度的一种方法。这种情况下,如果物理内存足够用,真正的文件IO只有写文件和第一次读的时候才会产生。
在Linux中文件IO主要通过 pidstat, iostat分析:
pidstat -d -p java_pid 1 3
KB_rd/s 表示每秒读取的KB数, KB_wr/s表示每秒写入的KB数, 还可以加入-t参数显示具体的线程信息。
iostat
iostat只能看到整个系统的文件IO,不能查看具体进程消耗情况。Device表示设备卷标名或分区名,tps是每秒的IO请求,是IO消耗关键指标;Blk_read/s表示每秒读的块数量,Blk_wrtn/s表示每秒写的块数量;Blk_read, Blk_wrtn表示总共读写的块数量;当%iowait占用很高的时候,就要关注IO消耗状况了,这时可以使用 iostat -x 观察:
r/s, w/s 表示每秒读写的请求数, await表示平均每次IO操作的等待时间,avgqu-sz表示等待请求的队列的平均长度,svctm表示平均每次设备执行IO操作的时间,util表示一秒之中有百分之几用于IO操作。
在Java应用中造成文件IO消耗严重的原因,通常是多个线程进行大量写入操作(如频繁写入日志文件)。这时可以通过pidstat或iostat结合jstack线程信息,找到消耗主体程序。
网络IO分析
在分布式Java应用中,网络IO的消耗是非常值得关注的,尤其注意网卡中断是不是均匀地分配到各CPU上(cat /proc/interrupts)。Linux使用sar分析网络IO消耗情况:
sar -n ALL 1 2
主要观注接包(rxpck/s),发包(txpck/s),接包失败(rxerr/s),发包失败(txerr/s),丢包(rxdrop/s),Socket信息(tcpsck , udpsck)。
由于无法观察具体进程的网络IO消耗,在网络IO消耗高时,只能线程dump,通常这些线程都在进行网络读写操作。在Java网络通信中,通常将对象序列化为字节流发送,反序列化生成对象。
内存分析
从Java应用角度上看,内存可分为两部分,即JVM内存与非JVM内存。在JVM中内存消耗主要体现在堆内存上,内存消耗过高会导致频繁GC甚至FullGC,CPU占用高,可以通过jmap, jstat, mat, visualvm等工具跟踪内存消耗情况;生产环境下,通常将 -Xms 和 -Xmx调整为相同的值,避免运行时不断申请内存。非JVM内存通常只有在创建线程或使用DirectByteBuffer时才会产生,最值得关注的是swap的消耗与物理内存的消耗。
vmstat
swpd表示虚拟内存已使用的部分(kb),free空闲物理内存,buff表示用于缓冲的内存,cache表示用于作为缓存的内存。swap下的si表示每秒从disk读到内存的数据量,so每秒从内存写入disk的数据量。swpd过高表示物理内存不够用,系统需要频繁从虚拟内存与disk交换数据,严重影响系统的性能。
sar -r 2 5
通过sar工具可以看到内存占用,空闲,buff, cache的情况。当物理内存空闲时,Linux会使用一部分内存用于buffer以及cache,以提高系统运行效率。因此可认为系统可用物理内存为 kbmemfree + kbbuffers + kbcached。
此外还可以使用top, pidstat -r -p [pid][interval][times]
pidstat -r -p 2448 1 5
参考资料
中断:http://blog.csdn.net/pxz_002/article/details/7327668
CPU占用分析:http://www.cnblogs.com/yjf512/p/3383915.html
林昊:分布式Java应用
JVM内存分析:http://my.oschina.net/feichexia/blog/196575
相关推荐
Java性能瓶颈可能导致系统响应变慢,用户体验下降,甚至可能导致服务器资源耗尽。而漏洞的存在则可能让系统面临被攻击的风险,因此,掌握有效的检测工具对于Java开发者来说是必备技能。本主题将深入探讨"JAVA性能...
讲解java应用下如何定位其性能瓶颈讲解java应用下如何定位其性能瓶颈讲解java应用下如何定位其性能瓶颈讲解java应用下如何定位其性能瓶颈
Java问题定位技术涉及到多方面知识点,从JVM到多线程、高并发以及性能调优工具等都是深入理解Java性能问题的核心组成部分。下面详细介绍这些知识点。 首先,JVM(Java虚拟机)是运行Java字节码的虚拟机进程,它是...
koTime是一个轻量级的springboot项目性能分析工具,通过方法调用链路追踪以及运行时长监控快速定位性能瓶颈,并进行可视化展示,还支持代码热更新与邮件预警; 实时监听方法,统计运行时长; web展示方法调用链路,...
本文将深入探讨如何理解和解决Java JVM的性能瓶颈问题。 1. **JVM概述** - JVM的作用:JVM作为Java程序的运行环境,负责解释执行字节码,提供垃圾回收机制,内存管理和多线程支持。 - 类加载机制:JVM通过类加载...
JavaMelody是一款强大的JAVA Web项目服务器性能监控工具,它能够实时、全面地监控应用程序的运行状态,帮助开发者和运维人员了解系统性能瓶颈,及时发现并解决问题。通过在Java Web应用中简单集成,JavaMelody就能...
这本书通过实际案例分析,指导开发者如何定位并解决性能瓶颈,提升系统运行效率。例如,书中可能会介绍如何使用JProfiler或VisualVM等工具进行性能监控,理解JVM垃圾回收机制,以及如何调整JVM参数以优化内存使用。...
在实际应用中,开发者经常会遇到性能瓶颈,以下是一些常见的影响Java EE性能的问题,以及相应的解决策略。 1. **缺乏正确的容量规划** - 容量规划是预测并满足IT环境未来需求的关键步骤。这包括硬件、中间件、JVM...
Performance Analyzer是一款专门针对Java性能的工具,它提供了深入洞察应用程序性能的能力,帮助开发者识别并解决性能瓶颈。 在Java性能分析中,我们通常关注以下几个核心知识点: 1. **JVM内存模型**:Java虚拟机...
Java 代码性能优化技巧总结 ...* 使用 profiling 工具来定位性能瓶颈。 * 使用 JVM 的参数来调整堆大小和垃圾收集器的行为。 Java 代码性能优化需要结合实际情况选择合适的优化技巧,充分发挥 Java 语言的性能潜力。
【Java性能优化】是开发者关注的重要话题,尤其是在服务器端应用中。Java自1990年代中期诞生以来,虽然凭借其跨平台特性受到欢迎,但性能一直是与C++等语言相比的一个短板。本文将从几个关键方面探讨Java性能优化。 ...
3. **易用性**:工具应该直观,便于理解和使用,以便快速定位性能瓶颈。 常见的Java性能分析工具有JProfiler、VisualVM、YourKit Java Profiler等。这些工具提供了深入的性能指标,如CPU使用率、内存分配、线程状态...
6. **监控与分析**:使用工具如VisualVM、JProfiler、YourKit等进行性能监控,分析CPU、内存、线程等状况,找出性能瓶颈。日志和Profiling可以帮助定位问题,而AOP(面向切面编程)可以用于记录方法执行时间,便于...
Java性能监控是优化Java应用程序的关键环节,它可以帮助开发者识别并解决性能瓶颈,确保程序的高效稳定运行。在Java中,有一些内置的工具可以用来监控和分析性能,包括内存使用、垃圾回收等方面。 首先,`jps`命令...
它能展示CPU使用率、内存占用、线程状态、类加载情况等信息,并支持JMX插件,帮助开发者定位性能瓶颈。通过VisualVM,我们可以进行堆内存分析、线程快照、方法追踪等功能,进行深入的性能诊断。 2. **JVM性能调优**...
文档还提到了Java代码的性能监控与问题定位方法,包括内存泄漏检测、JVM内存泄漏分析、JVM启动参数介绍、认识JVM和JVM性能瓶颈。通过实例分析了JVM内存泄漏的几种情况,并展示了如何使用JProfile等工具来跟踪内存...
- 结果分析部分会对各项性能指标进行详尽的解读,对比预期性能,指出潜在瓶颈和优化方向。 总结来说,这份性能测试报告全面涵盖了测试场景的设定、监控、执行以及结果分析,为优化系统性能提供了依据。通过深入...
2.通过Java线程堆栈进行性能瓶颈分析 3.Java内存泄漏分析和堆内存设置 4.关于并发和多线程 5.幽灵代码 6.常见的Java泥潭 7.JVM 8.关于字符集与编码 9.常用分析工具 10.Java最佳实践 11.关于数据库 12.工程实践 13....