zoukankan      html  css  js  c++  java
  • 6-JVM常用工具和优化

    JVM 常用工具和优化

    JDK 自带的

    jconsole

    jvisualvm

    三方的工具

    arthas

    调优关注点(内存、GC):

    内存

    • MAT
    • XElephant
    • 在线:perfma

    GC

    拿到GC日志,分析GC日志(吞吐量,停顿时间,垃圾回收次数;这三个是评判垃圾收集器好坏的标准)

    • 本地:GCViewer
    • 在线:gceasy.io

    在什么情况下调优

    体现系统性能的参考因素

    首先我们需要知道系统当前的运行状况,也就是系统的性能好坏,才能判断是否需要调优。如果系统的响应时间很短,计算机的资源使用也很低,那我们做系统调优就完全是为了调优而调优。那么衡量系统性能的指标到底有哪些呢?

    • 响应时间:响应时间是衡量系统性能的重要指标之一,响应时间越短,性能越好,一般一个接口的响应时间是在毫秒级。响应时间还包括数据库响应时间、服务端响应时间、网络响应时间、客户端响应时间。
    • TPS:指系统接口的 TPS(每秒事务处理量),因为 TPS 体现了接口的性能,TPS 越大,性能越好。在系统中,吞吐量分为两种:磁盘吞吐量和网络吞吐量。
    • 计算机资源分配使用率:通常由 CPU 占用率、内存使用率、磁盘 I/O、网络 I/O 来表示资源使用率。这几个参数好比一个木桶,如果其中任何一块木板出现短板,任何一项分配不合理,对整个系统性能的影响都是毁灭性的。

    JVM 调优都做些什么?

    具体来说 JVM 调优需要包括两方面:合理地设置 JVM 的内存空间和选择合适的垃圾回收器。

    • 内存空间的分配设置:JVM 内存分配不合理带来的性能表现并不会像内存溢出问题这么突出,最直接的表现就是频繁的 GC,这会导致上下文切换等性能问题,从而降低系统的吞吐量、增加系统的响应时间。具体的实现包括调整堆内存空间减少 Full GC、调整年轻代减少 MinorGC、设置合理的 Eden 和 Survivor 区的比例。
    • 选择合适的垃圾回收器:垃圾回收主要是指堆和方法区的回收,堆中的回收主要是对象的回收,方法区的回收主要是废弃常量和无用的类的回收。垃圾收集器的种类很多,不同的场景有不同的选择。对于每次操作的响应时间要求比较高的,我们可以选择响应速度较快的 GC回收器,比如 CMS 回收器和 G1 回收器;而对系统吞吐量有较高要求时,就可以选择 Parallel Scavenge 回收器来提高系统的吞吐量。

    是否需要 JVM 调优?

    一般项目肯定是不需要进行 JVM 调优的,因为 JVM 本身就是为这种低延时、高并发、大吞吐的服务设计和优化的,我们很少需要去改变什么。所以,我们往往更偏重于应用服务本身的调优。

    在一些应用中,比如大数据计算引擎,是一种非常极端的 JVM 应用,对延时的要求并不高,但对吞吐量要求很高,会有大量的短生命周期对象产生,同时也有大量的对象生存时间非常久,我们就需要对特定的一些 JVM 参数进行修改。

    再比如生产环境中出现内存溢出,我们需要判断是由于大峰值下没有限流,瞬间创建大量对象而导致的内存溢出,还是是由于内存泄漏而导致的内存溢出。对于内存泄漏导致的,这种问题就是程序的 Bug,我们需要及时找到问题代码进行修改,而不是调整 JVM。

    JVM 在很大程度上减轻了 Java 开发人员投入到对象生命周期管理的精力。在使用对象的时候,JVM 会自动分配内存给对象,在不使用的时候,垃圾回收器会自动回收对象,释放占用的内存。所以一般情况下我们是不需要调优的。当然事无绝对,某些特殊场景就需要我们进行参数调整,但调整的前提一定是你对 JVM 的运行原理非常熟悉才行。

    JVM错误排查与解决案例

    JVM性能优化到底从发现到解决的历程:发现问题-排查问题-解决问题

    案列一:

    发现问题:JVM日志 gc.log 文件,通过JVM工具(比如:gceasy)查看并发现问题;比如GC的次数过多;可以通过工具查看到GC次数【新生代和老年代分别的GC次数】。GC频繁:如何判断GC频繁呢?有个参照【比如服务刚上线GC5次,运行一段时间后10次,在之后30次,在之后50次,依次类推】

    排查问题:打印出JVM GC日志,查看minorGC(新生代GC)或者majorGC(老年代GC)

    解决问题:适当增加堆内存空间,或者选择合适的垃圾收集器

    案例二:

    发现问题:OOM

    排查问题:在JVM参数中配置,如果发生了OOM错误时自动dump下相关的.hprof文件,对该文件通过工具(比如MAT或者在线的perfma)进行分析;分析之后当找到占用内存比较大的对象对应的线程的业务代码(可能是程序死循环,或者后端程序并发量比较大)

    解决问题:如果是并发量比较大,就减少对后端程序的访问;通过Nginx增加机器,负载均衡,权重比例

    案例三

    发现问题:CPU负载过高

    排查问题:命令:top jps jinfo jstat jmap 等这些命令灵活配合使用查看;可能是服务程序处理压力过大

    解决问题:具体看情况而论,可以集群部署、或者通过中间件(MQ、Kafka等)实现异步请求

    案例四

    发现问题:死锁

    排查问题:可以通过 jstack 命令去查看相关线程锁的信息

    解决问题:找到对应的业务代码,进行修改;或者使用zk、redis实现分布式锁

    案例五

    发现问题:线程池不够用了

    排查问题:通过JDK的工具 jconcole jvisualvm 查看哪些线程得不到释放的

    解决问题:适当的对后端代码优化,及时释放资源、合理的设置线程池中的参数(大小)

    赵小胖个人博客

  • 相关阅读:
    Mayan游戏 (codevs 1136)题解
    虫食算 (codevs 1064)题解
    靶形数独 (codevs 1174)题解
    黑白棋游戏 (codevs 2743)题解
    神经网络 (codevs 1088) 题解
    The Rotation Game (POJ 2286) 题解
    倒水问题 (codevs 1226) 题解
    银河英雄传说 (codevs 1540) 题解
    生日蛋糕 (codevs 1710) 题解
    第一章 1.11 高阶函数
  • 原文地址:https://www.cnblogs.com/Sky0914/p/12922964.html
Copyright © 2011-2022 走看看