`
michaellou
  • 浏览: 55715 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

jvm 性能调优

阅读更多
jvm性能调优(转发)

我一直觉得性能优化是出力不讨好的事情,因为花费了大量的精力,经常收获甚微。不过还是工作还是要做的,就稍微总结一些。

个人性能优化不要经常做,除非觉得系统存在相当严重的性能问题,因为优化通常意味着要改动,在系统没有足够多的test case和auto test保证下,后果通常是很恐怖的。现在的硬件已经相当廉价,如果可以,选择增加适当的硬件投入是一个不错的选择。

系统是否存在严重的性能问题,光靠感觉是不够的,给老板的report如果没有几组量化的数据,是很难不被骂的。现在的性能测试工具还是蛮多的, 比较好用的包括load runner和jmeter。前者可以自动录制测试脚本,后者通过第三方工具也可以录制自动测试脚本。通常测试工具都有格式良好的report输出,在 web应用中有几个指标需要我们给予更多关注:a. Average Hits per Second,b. 90 Percent transaction response time,c. Average Throughput (bytes/second)。需要注意的是,指标a和指标b是有一些相互约束关系的,很难做到系统有很高的并发请求量,同时请求的响应时间又很小,就好 象很难让“马儿跑得快”又让“马儿不吃草”,我们需要在二者之间找到平衡点。当然,不同工具的指标名称可以不同,但这三个指标通常都会有对应的数据。一个 性能测试报告,是在一定的前提下,比如怎样的硬件设置,怎样的网络环境,怎样的请求数据,怎样的并发模拟,以及多少的并发量等,不同的测试环境所得到的数 据可能相差甚远。

如果系统确实存在性能问题,比如经常宕机,或者响应时间很慢,处理的并发量很小,就不得不进入性能优化阶段。性能优化包括几个环节:运行环境参数调优,数据库调优,应用调优等。

Jvm中提供了丰富的参数供我们设置,合理的设置这些参数,可以有效的提高系统的性能。在列出这些参数之前,先大致介绍一些jvm的heap结构。Jvm的heap包括三部分,其中permanent generation, new generation以及tenured(old) generation。其中permanent generation是jvm自用的区域,用于存放反射代理和class,所以如果应用的class相当多时,就可以考虑将这一块区域放大一些。New generation和tenured generation是java应用的heap区,其中new generation有分为eden space, from space和to space,eden space用于存放新创建的对象(eden是上帝创造人时设立的,呵呵),from & to space都是survivor space。当jvm minor gc时,会将eden space的数据copy到survivor甚至tenured generation,所以每一次minor gc时,eden space区域都会被清空。Tenured generation用于存放长寿的对象,当其空间不够用时,会促使jvm major gc,major gc通常是很耗时的。合理的设置各个区的大小,可以快速的mimor gc,避免频繁的major gc。To summarize, you want to maximize quick minor collections and minimize major collections。常用的参数包括:

-Xmx 设置Java heap size最大值,注意这里的heap size = new generation + tenured generation,是不包括permanent generation的

-Xms 设置Java heap size 初始值

-XX:NewRatio new/old generation sizes的比率

-XX:NewSize new generation heap size

-XX:MaxNewSize 可以通过NewRatio和-Xmx计算得到

-XX:SurvivorRatio eden/survivor space size比率

-XX:PermSize permanent generation初始值

-XX:MaxPermSize Permanent Generation最大值

这些值得设置可以通过经验获得,也可以通常Jvm log分析得到。Jvm的一些参数可以输出有效的log文件:

-verbose:gc – 输出一些gc信息

-XX:+PrintGCDetails – 输出gc详细信息

-XX:+PrintGCTimeStamps – 包含时间戳信息

-XX:+PrintHeapAtGC – 包括gc前后heap状况

-XX:+PrintTenuringDistribution – 输出对象年龄或者tenured generation其他信息

-XX:+PrintHeapUsageOverTime - Print heap usage and capacity with timestamps

-Xloggc:filename – 输出gc信息到日志文件

通常在jvm中加入下面的设置,足以满足大多数要求:set JAVA_OPTS=%JAVA_OPTS% -verbose:gc -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC。不过拿到日志,对着一大堆的数字,也是天书一本,很难直接得到有效的信息。Jdk 1.6.0的gc log输出如下:

{Heap before GC invocations=0 (full 0):

def new generation   total 254464K, used 213053K [0x10030000, 0x20030000, 0x20030000)

eden space 246784K,  86% used [0x10030000, 0x1d03f7d8, 0x1f130000)

from space 7680K,   0% used [0x1f130000, 0x1f130000, 0x1f8b0000)

to   space 7680K,   0% used [0x1f8b0000, 0x1f8b0000, 0x20030000)

tenured generation   total 262144K, used 0K [0x20030000, 0x30030000, 0x30030000)

the space 262144K,   0% used [0x20030000, 0x20030000, 0x20030200, 0x30030000)

compacting perm gen  total 16384K, used 16383K [0x30030000, 0x31030000, 0x34030000)

the space 16384K,  99% used [0x30030000, 0x3102ff38, 0x31030000, 0x31030000)

No shared spaces configured.

12.928: [Full GC 12.928: [Tenured: 0K->6352K(262144K), 0.1784526 secs] 213053K->6352K(516608K), [Perm : 16383K->16383K(16384K)], 0.1785568 secs]

Heap after GC invocations=1 (full 1):

def new generation   total 254464K, used 0K [0x10030000, 0x20030000, 0x20030000)

eden space 246784K,   0% used [0x10030000, 0x10030000, 0x1f130000)

from space 7680K,   0% used [0x1f130000, 0x1f130000, 0x1f8b0000)

to   space 7680K,   0% used [0x1f8b0000, 0x1f8b0000, 0x20030000)

tenured generation   total 262144K, used 6352K [0x20030000, 0x30030000, 0x30030000)

the space 262144K,   2% used [0x20030000, 0x20664290, 0x20664400, 0x30030000)

compacting perm gen  total 16384K, used 16383K [0x30030000, 0x31030000, 0x34030000)

the space 16384K,  99% used [0x30030000, 0x3102ff38, 0x31030000, 0x31030000)

No shared spaces configured.

}

不过通过格式分析,可以写成java程序来处理这些日志,生成有用的report。我喜欢的report是chart,所以我把这个日志文件转换成图表方式,可以清晰的看到jvm heap size发生的变化,以及gc的频率,和full gc的时间。通过分析heap size的使用,可以设置合理的jvm运行参数。

在java应用中,虽然不太容易出现内存泄漏的问题,因为jvm会不定期的进行 gc。但是因为程序的不合理写法,也会导致一些数据不能被收集。典型的状况是在hashmap中放置大量不用的数据,而没有及时的清理。在web应用中, 很多人喜欢在session放放置状态数据,而没有清理,也是内存泄漏的一个原因。在session中存放数据还好,因为session终究会有过期时 间,但是如果在class的static变量中放置数据,那就怎么样也没办法了。诊断应用中是否存在内存泄漏也有一些方法,通过分析jvm gc log就是一个直观的方式。通过分析gc after heap的变化趋势,如果gc after heap稳 步上升,及时full(major) gc后,仍然不能降下来,通常就意味着存在内存泄漏了。当然也有情况是,的确有一些数据是application scope的,但是要确认除了这些数据,是否还存在一些unexpected数据一直占据内存。可以通过Jprofile的memory views来观察class的对象数,在一段请求过后,如果还存在一些class的instance数目相当多,就可以判断这个class可能会是问题的 根源。

在o/r mapping盛行的今天,数据库已经和我们渐行渐远,我们不用建数据库和表结构,不用写sql查询,一切都是对象操作,除非存在性能问题,否则没有人会 乐意关注一些数据库。但是不可否认的是,今天的java应用,大多数依然是数据集中式的,需要和数据库频繁的交互,而且数据库也很容易成为性能的瓶颈。数 据库的调优包括三部分:数据库参数的设置,表结构以及sql代码优化。

大多数数据库的参数都相当多,调优所需要的知识很复杂,这也是现在professional的dba特别贵的原因,这一块俺也没有什么经验可分享。

至于表结构,因为现在o/r mapping工具已经包揽了这项工作,所以已经转为对象结构的优化了。我的理解是可以适当的非规范化对象结构,包括允许一些冗余属性,同时减少一些双向 关联,过往的经验告诉我,双向关联通常都是性能的杀手。有一块需要做的是索引,合理的索引可以成倍的提高数据库性能。不过这一块做起来,通常要考虑应用中 出现的sql。Index是一把双刃剑,很多时候可以提高查询的速度,但同样其存在维护成本,导致update性能下降。而且是否用得上index,还要 看查询返回的结果集,如果查询的结果集很多,此时使用index,反而性能会下降,因为需要进行两次访问,还不如直接table scan来的快。

在sql调优时,可以先挑出性能很差的同时又频繁执行的sql,可以通过Jprofile的CPU Views过滤出Jdbc calls。这些sql可以拿到相应的数据库工具中调优,数据库引擎通常会根据数据库的一些metadata和statistics,生成一个 execution plan,通过这个execution plan,可以找到优化的途径。通常的思路是,表访问策略(index scan, table scan),表连接策略(sort merge join, nested loop join, hash join),表顺序(驱动表的选择),是否充分并行等。通过调整sql的写法,会使dbms使用不同的执行计划。当然要得到有效的执行计划,需要时常更新 数据库的statistics,很多是否发现index没用上,后来发现原来是这个原因。此外,sql语句还有一些其他好的习惯,简单列出一些:

避免where子句中出现or,事实证明or的性能通常不如in;

避免like子句,尤其是通配符%在前面;

避免where子句中在indexed column中加函数,尽量将函数转移到的比较运算符右边去,否则没办法使用到索引;

where中column出现的顺序和index的顺序一致;

避免使用select *,不要偷懒,还是自己写要取那些列,即使是获得所有的列;

一句性能优良的sql,是不太容易写出的,其实这也是大量o/r mapping tools出现的一个原因,想让o/r mapping生成一个很好的sql不容易,不过想让其生成一个很烂的sql也同样式不容易的,毕竟综合了很多人的经验在其中。

应用的调优,需要具体情况具体分析,通常code review是一个很好的时机,分析具体代码是否存在性能缺陷。此外,通过Jprofile观察,其CPU Views列出了所有method的执行时间,可以找到其中的性能缺陷,重点分析。这种调整通常涉及到算法的优化和结构的调整,不过俺也没有具体的经验总 结可以提供。
分享到:
评论

相关推荐

    深入理解Java虚拟机(jvm性能调优+内存模型+虚拟机原理).zip

    《深入理解Java虚拟机》是一本深度探讨Java虚拟机(JVM)的著作,涵盖了JVM性能调优、内存模型以及虚拟机原理等多个关键领域。本文将基于这些主题,详细阐述其中的重要知识点。 首先,我们要了解Java虚拟机(JVM)...

    jvm性能调优+内存模型+虚拟机

    jvm性能调优+内存模型+虚拟机 jvm性能调优+内存模型+虚拟机 jvm性能调优+内存模型+虚拟机

    个人总结之—JVM性能调优实战

    ### 个人总结之—JVM性能调优实战 #### 概述 本文档是一篇关于JVM(Java虚拟机)性能调优的经典实战总结。在实际应用开发与维护过程中,JVM性能调优是一个非常重要的话题,它直接关系到应用程序运行效率、资源利用...

    JAVA JVM性能调优监控工具详解

    ### JAVA JVM性能调优监控工具详解 在Java开发过程中,特别是在企业级应用中,经常会遇到各种性能瓶颈问题,如内存溢出(`OutOfMemoryError`)、内存泄露、线程死锁、锁争用等问题。这些问题如果不能及时有效地解决...

    JVM性能调优总结.docx

    JVM性能调优总结 JVM性能调优是Java开发中非常重要的一方面,直接影响到系统的性能和稳定性。本文将总结JVM性能调优的经验和技巧,并提供一些实用的配置参数和建议。 一、堆大小设置 堆大小是JVM性能调优中的一个...

    006-jvm性能调优

    JVM性能调优 JVM(Java Virtual Machine)是Java程序执行的核心组件,负责执行Java字节码指令。JVM性能调优是Java开发者应该掌握的重要技能,以下是JVM性能调优的知识点总结: JVM基础知识 * 虚拟机:是一种软件...

    JVM性能调优-JVM内存整理及GC回收.pdf

    了解Java对象引用类型、垃圾回收算法以及分代处理垃圾的概念是进行JVM性能调优的基础。这些知识点对于准备Java面试的开发者来说,是必须掌握的重要内容,同时也是深入理解JVM内存管理和性能优化的基础。

    基于Spring Boot框架的JVM性能调优与内存管理.zip

    基于Spring Boot框架的JVM性能调优与内存管理 项目简介 本项目是一个基于Spring Boot框架的Java应用程序,专注于JVM性能调优与内存管理。通过深入探讨JVM的内存分配、垃圾收集、线程管理、并发控制等核心概念,...

    JVM性能调优全套代码

    代码包含了T01到T05,下载后建议使用markdwon软件食用,谢谢大家

    JVM性能调优经典教程

    JVM性能调优是一项关键技术,旨在优化JVM的内存管理、垃圾收集、类加载等方面,以提升程序运行速度、减少内存占用并避免系统崩溃。本教程"JVM性能调优经典教程"由马士兵老师倾力讲解,旨在帮助Java开发者进阶,掌握...

    JVM性能调优分析过程

    本文将详细解析JVM性能调优分析的过程,并提供常见参数选择配置的建议。 首先,进行JVM参数调优时,我们需要考虑以下几个步骤: 1. **对象占用内存计算**:了解业务系统每秒钟创建的对象数量及其占用的内存空间,...

    JVM性能调优.docx

    以下是根据提供的内容,对JVM性能调优的一些关键知识点的详细解释: 1. **内存设置**: - `-Xmx` 和 `-Xms` 参数用于设置Java堆的最大和初始内存大小。在示例中,它们都设置为2000M,这意味着JVM启动时会分配2GB的...

    JVM性能调优-JVM内存整理及GC回收.docx

    JVM性能调优-JVM内存整理及GC回收 JVM(Java Virtual Machine)性能调优是 Java 开发者需要掌握的重要技能之一。 JVM 的性能调优主要涉及到 JVM 内存整理、垃圾回收(GC)机制等方面。 Java 中的值传递和引用传递...

    JVM性能调优-JVM内存整理及GC回收

    《JVM性能调优-JVM内存整理及GC回收》是一份深入探讨Java虚拟机(JVM)优化的重要学习资料,特别适合对JAVA编程有经验的开发者。这份文档详细阐述了JVM性能调优的关键概念,包括JVM内存模型、垃圾回收(Garbage ...

    深入理解Java虚拟机(jvm性能调优+内存模型+虚拟机原理).txt

    深入理解Java虚拟机详细视频教程,包括jvm性能调优、Java内存模型及虚拟机原理。有详细的文档资料,配合深入理解Java虚拟机书籍学习效果更佳

    JVM性能调优监控工具jps、jstack、jmap、jhat、jstat使用详解.docx

    JVM性能调优监控工具jps、jstack、jmap、jhat、jstat使用详解 本文将对一些常用的 JVM 性能调优监控工具进行介绍,包括 jps、jstack、jmap、jhat、jstat 等工具的使用详解。这些工具对于 Java 程序员来说是必备的,...

    JVM性能调优和常见问

    JVM性能调优和常见问题!JVM结构和常见错误解决

    jvm性能调优实战篇插件

    jvm性能调优实战篇视频

    深入理解JVM性能调优和内存模型,垃圾回收,虚拟机原理,经典视频教程

    《深入理解JVM性能调优和内存模型,垃圾回收,虚拟机原理,经典视频教程》是一套详尽的教育资源,旨在帮助Java开发者深入探索Java虚拟机(JVM)的内部工作机制,提升性能优化的能力。本教程共包含110讲,内容丰富,适合...

Global site tag (gtag.js) - Google Analytics