java性能调优的基本知识
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Java堆是指在程序运行时分配给对象生存的空间。
通过-mx/-Xmx和-ms/-Xms来设置起始堆的大小和最大堆的大小。
根据自己JDK的版本和厂家决定使用-mx和-ms或-Xmx和-Xms。
Java堆大小决定了垃圾回收的频度和速度,Java堆越大,垃圾回收的频度越低,速度越慢。
同理,Java堆越小,垃圾回收的频度越高,速度越快。
要想设置比较理想的参数,还是需要了解一些基础知识的。
Java堆的最大值不能太大,这样会造成系统内存被频繁的交换和分页。
所以最大内存必须低于物理内存减去其他应用程序和进程需要的内存。
而且堆设置的太大,造成垃圾回收的时间过长,这样将得不偿失,极大的影响程序的性能。
以下是一些经常使用的参数设置:
1) 设置-Xms等于-XmX的值;
2) 估计内存中存活对象所占的空间的大小,设置-Xms等于此值,-Xmx四倍于此值;
3) 设置-Xms等于-Xmx的1/2大小;
4) 设置-Xms介于-Xmx的1/10到1/4之间;
5) 使用默认的设置。
大家需要根据自己的运行程序的具体使用场景,来确定最适合自己的参数设置。
除了-Xms和-Xmx两个最重要的参数外,还有很多可能会用到的参数,这些参数通常强烈的依赖于垃圾收集的算法,所以可能因为JDK的版本和厂家而有所不同。
但这些参数一般在Web 开发中用的比较少,我就不做详细介绍了。
在实际的应用中注意设置-Xms和-Xmx使其尽可能的优化应用程序就行了。
对于性能要求很高的程序,就需要自己再多研究研究Java虚拟机和垃圾收集算法的机制了。
可以看看曹晓钢翻译的《深入Java虚拟机》一书。
Java程序性能调优的基本知识和JDK
调优
一基本知识
1.1 性能是什么
在性能调优之前,我们首先来了解一下性能是什么?关于性能,我想每个学习过Java的人都能列
出几点,甚至可以夸夸其谈。
在《Java TM Platform Performance》一书中,定义了如下五个方面来作
为评判性能的标准:
1) 运算的性能——哪一个算法的执行性能最好?
2) 内存的分配——程序运行时需要耗费多少内存?
3) 启动的时间——程序启动需要多长时间?这在Web项目中的影响不大,但要注意部分程序需要
部署或运行在客户端时的情形(比如applet程序)。
4) 程序的可伸缩性——在压力负载的情况下,程序的性能如何?
5) 性能的感知——用户在什么情况下会觉得程序的性能不好?
以上五个方面,在具体的使用场景可以有选择的去评判。
至于这五方面的性能调优,在后续的章节
中将会陆续的给以相应的性能调优策略。
1.2 调优的规则
我们只需要关心对我们程序有影响,可以察觉到的性能问题,而不是每一个类中的每一个方法我们都需要想方设法的提高性能。
如果程序的性能没有达到我们所期望的要求,我们才需要考虑如何优化性能。
同样的,晦涩的代码虽然提高了程序的性能,但同时可能带给我们的是维护的噩梦。
我们需要折中的考虑以上两种情况,使得程序的代码是优美的,并且运行的足够快,达到客户所期望的性能要求。
优化代码甚至会导致不良的结果,Donald Knuth(一位比较牛比较有影响的人物,具体是谁,我也忘了,谁知道,可以告诉我一下,谢谢!)曾说过,“Premature optimization is the root of all evil”。
在开始性能调优前,需要先指出不优化代码的一些理由。
1) 如果优化的代码已经正常工作,优化后可能会引入新的bug;
2) 优化代码趋向于使代码更难理解和维护;
3) 在一个平台上优化的代码,在另一个平台上可能更糟;
4) 花费很多时间在代码的优化上,提高了很少的性能,却导致了晦涩的代码。
确实,在优化前,
我们必须认真的考虑是否值得去优化。
1.3 调优的步骤
一般我们提高应用程序的性能划分为以下几个步骤:
1) 明确应用程序的性能指标,怎样才符合期望的性能需求;
2) 在目标平台进行测试;
3) 如果性能已经达到性能指标,Stop;
4) 查找性能瓶颈;
5) 修改性能瓶颈;
6) 返回到第2步。
二 JDK调优
2.1 选择合适的JDK版本
不同版本的JDK,甚至不同厂家的JDK可能都存在着很大的差异,对于性能优化的程度不同。
一般来说,尽可能选择最新发布的稳定的JDK版本。
最新的稳定的JDK版本相对以前的JDK版本都会做一些
bug的修改和性能的优化工作。
2.2 垃圾收集Java堆的优化
垃圾收集就是自动释放不再被程序所使用的对象的过程。
当一个对象不再被程序所引用时,它所引用的堆空间可以被回收,以便被后续的新对象所使用。
垃圾收集器必须能够断定哪些对象是不再被引用的,并且能够把它们所占据的堆空间释放出来。
如果对象不再被使用,但还有被程序所引用,这时是不能被垃圾收集器所回收的,此时就是所谓的“内存泄漏”。
监控应用程序是否发生了内存泄漏,有一个非常优秀的监控工具推荐给大家——Quest公司的JProbe工具,使用它来观察程序运行期的内存变化,并可产生内存快照,从而分析并定位内存泄漏的确切位置,可以精确定位到源码内。
这个工具的使用我
在后续的章节中还会做具体介绍。
Java堆是指在程序运行时分配给对象生存的空间。
通过-mx/-Xmx和-ms/-Xms来设置起始堆的大小和最大堆的大小。
根据自己JDK的版本和厂家决定使用-mx和-ms或-Xmx和-Xms。
Java堆大小决定了垃圾回收的频度和速度,Java堆越大,垃圾回收的频度越低,速度越慢。
同理,Java堆越小,垃圾回收的频度越高,速度越快。
要想设置比较理想的参数,还是需要了解一些基础知识的。
Java堆的最大值不能太大,这样会造成系统内存被频繁的交换和分页。
所以最大内存必须低于物理内存减去其他应用程序和进程需要的内存。
而且堆设置的太大,造成垃圾回收的时间过长,这样将得不偿失,极大的影响程
序的性能。
以下是一些经常使用的参数设置:
1) 设置-Xms等于-XmX的值;
2) 估计内存中存活对象所占的空间的大小,设置-Xms等于此值,-Xmx四倍于此值;
3) 设置-Xms等于-Xmx的1/2大小;
4) 设置-Xms介于-Xmx的1/10到1/4之间;
5) 使用默认的设置。
大家需要根据自己的运行程序的具体使用场景,来确定最适合自己的参数设置。
除了-Xms和-Xmx 两个最重要的参数外,还有很多可能会用到的参数,这些参数通常强烈的依赖于垃圾收集的算法,所以可能因为JDK的版本和厂家而有所不同。
但这些参数一般在Web开发中用的比较少,我就不做详细介绍了。
在实际的应用中注意设置-Xms和-Xmx使其尽可能的优化应用程序就行了。
对于性能要求很高的程序,就需要自己再多研究研究Java虚拟机和垃圾收集算法的机制了。
可以看看曹晓钢翻译的《深入Java
虚拟机》一书。
Web 应用程序调优指南时间:2009-09-09 22:45:36来源:网络作者:未知点击:120次
一.成功的应用都是相似的,失败的应用各有各的失败
一.成功的应用都是相似的,失败的应用各有各的失败
对于Web应用来说,影响性能的集中体现在网络/CPU/内存/IO/数据库/缓存这6个环节的处理上。
一个稳定应用的特征应该包括:
1. 网络流量平稳,连接数保持稳定
2. 低CPU负载
3. 内存曲线平稳
4. IO高响应
5. 数据库的低负载,高响应
简单的来说,对于每个不稳定的应用来说,都会有一个瓶颈,通过以上的工具分析,加上自己的判断,找到那个瓶颈,解决它!
我们可以通过以下监控工具可监控到应用的各项指标
1. 网络监控工具Cacti ,可以监控到整个服务器的流量/硬盘/CPU负载等情况
2. JVM 监控JConsole (JDK 1.5 以上版本自带), %JA V A_HOME%\bin\jconsole
Java 启动加上一下参数:
-Dcom.sun.management.jmxremote.port=5004 (监控端口)
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
3. Visual VM (JDK 1.6_07 以上版本自带) %JA V A_HOME%\bin\jvisualvm
配置方法同JConsole , Visual VM 比JConsole 多了一个实用功能Thead Dump.
4. Kill -3 来获取Thead Dump
TheadDump可以很清晰的告诉你JVM当前正在做什么,内存里有哪些进程,是否有死锁。
重点观察RUNNABLE 和LOCK 是否有死锁。
5. 数据库查看
MySql 的show processlist命令
二.调优手段和策略
1. 网络层优化
不同类型的应用所能承受的网络负载各不相同,对于长连接应用来说,比如下载应用,所能承受的连接数就相对低,对于短链接应用,比如计数应用,所能承受的连接数就相对高,对于一般有数据库的应用来说,每秒的连接数保持在700以下都是没问题的。
这里调优的方面包括:
1)Linux可以优化网络的TCP参数,提高网络的响应,
2)增加服务器实现负载均衡,目的降低单台服务器流量
3)优化程序,尽可能的减少处理的时间,如果一定有长时间处理的场景,可以采用异步方式处理。
先返回一个请求ID,然后客户端再通过这个ID来获得结果。
2. CPU优化
就目前的硬件环境来看,CPU都不会是一个瓶颈。
如果CPU出现负载高,基本上都是程序处理不当引起,比如有深度递归或者循环或者频繁写磁盘,一旦出现高负载,会引起一系列的连锁反应,响应降低,连接数增加。
这个环节主要是优化程序:
1)减少循环和递归
2)减少synchronized 的用法。
对于多服务器场景,要实现锁机制,用synchronized 不一定适合。
Synchronized 使用不当,极容易造成死锁。
3)减少死锁发生的可能性。
JConsole提供了一个检测死锁的方法,TheadDump 也可以分析死锁。
3. 内存优化
对于Java应用来说,内存调优是关键。
先来认识一下Java内存的构成和垃圾回收的机制:
堆是应用程序使用的主要部分,一旦堆满,应用程序就会抛出Out Of Memory错误。
具体关于堆的构成以及垃圾回收算法,可以参考文档:
/logs/4712392.html
这个环节的优化:
1) 增加JVM内存,使得可使用的堆内存尽可能多,延长垃圾回收的时间。
需要注意的是,一般来说,回收1G内存所需要的时间是7秒左右,如果这个时间访问量比较高,极容易导致应用停止响应,所以并非是越大内存越好。
通过增加XX:+PrintGCDetails 参数可以观察到垃圾回收的频率和时间2) 调整垃圾回收策略,加快JVM的回收,因为Web应用响应高,很多都是无用内存,加快回收可以保证有效堆会更多,这种方式会消耗更多的CPU。
4. IO 优化
为了提高IO的响应,尽可能的不要把所有文件写到同一个目录下,所有的请求集中在一个磁盘上。
当一个目录下超过2000个文件,就会导致IO响应下降。
这个环节调优包括
1) 采用更快的IO设备,比如NAS 存储设备
2) 如果可能,将文件缓存到内存,或者先写内存,定时回写磁盘。
3) 将读和写操作分开来实现。
比如一个线程只写,一个线程只读。
5. 数据库优化
这个环节可以优化的地方比较多,通常由以下几个方面:
1)建立索引
2)对于复杂的业务逻辑,采用存储过程实现
3)对于大数据量,采用归档或者分表方式进行处理。
比如100万的数据要0.1秒就读取出来,如果采用分表,降低的数据规模,实现这个是不难的。
6. 缓存
这个的最终目的是为了保证以上各个环节顺畅。
缓存从架构上来分包括
1)集中式缓存,如Memcached
2)分布式缓存,如OpenJPA 的二级缓存,采用JGroup 方式来同步
从类型上来分包括
1)页面缓存,页面缓存可以定时更新
2)数据缓存,可以先把数据缓存到内存,然后定时写入数据库。
三.构架一个稳定应用
1. 应用分类
首先要认识到,不同的应用需要的资源和处理的方式是不一样的,所以在开发一个应用之前,要认识到应用的特征及其可能的瓶颈。
为每类应用定制一个解决套餐,是成功的基础。
2. 可重用的处理模型
要建立一个可重用的程序库,比如计数框架,缓存框架,模板框架。
当你需要的时候,不是重新开发,而是拿过来直接使用就可以了。
3. 持续监控和改进
随着时间的推移,应用所需要的资源也会不同,有些应用可能比预想的差,需要减少资源,有些发展迅猛,需要增加资源。
这些都需要我们建立一个可持续的监控机制。
四.常见不稳定问题处理办法
1. 内存只涨不降
查看一下网络流量,看是否是持续增加,如果网络流量正常,很可能你的程序有内存泄漏问
题。
建议的办法:改程序/增加内存或者提高垃圾回收的频率。
更多有待完善中。
本指南不是一个教科读书,更多的是经验总结,目的是为了开发高响应/高并发的Web 应用,会不断的补充完善,如果需要具体的帮助,可以Google一下。
本篇文章来源于:开发学院 原文链接:/2009/0909/15149.php
一、概述
随着数据库在各个领域的使用不断增长,越来越多的应用提出了高性能的要求。
数据库性能调优是知识密集型的学科,需要综合考虑各种复杂的因素:数据库缓冲区的大小、索引的创建、语句改写等等。
总之,数据库性能调优的目的在于使系统运行得更快。
调优需要有广泛的知识,这使得它既简单又复杂。
说调优简单,是因为调优者不必纠缠于复杂的公式和规则。
许多学术界和业界的研究者都在尝试将调优和查询处理建立在数学基础之上。
称调优复杂,是因为如果要完全理解常识所依赖的原理,还需要对应用、数据库管理系统、操作系统以及硬件有广泛而深刻的理解。
数据库调优技术可以在不同的数据库系统中使用。
如果需要调优数据库系统,最好掌握如下知识:1)查询处理、并发控制以及数据库恢复的知识;2)一些调优的基本原则。
这里主要描述索引调优。
二、索引调优
索引是建立在表上的一种数据组织,它能提高访问表中一条或多条记录的特定查询效率。
因此,适当的索引调优是很重要的。
对于索引调优存在如下的几个误区:
误区1:索引创建得越多越好?
实际上:创建的索引可能建立后从来未使用。
索引的创建也是需要代价的,对于删除、某些更新、插入操作,对于每个索引都要进行相应的删除、更新、插入操作。
从而导致删除、某些更新、插入操作的效率变低。
误区2:对于一个单表的查询,可以索引1进行过滤再使用索引2进行过滤?
实际上:假设查询语句如下select * from t1 where c1=1 and c2=2,c1列和c2列上分别建有索引ic1、ic2。
先使用ic1(或ic2)进行过滤,产生的结果集是临时数据,不再具有索引,所以不可使用ic2(或ic1)进行再次过滤。
索引优化的基本原则:
1、将索引和数据存放到不同的文件组
没有将表数据和索引数据存储到不同的文件组,而不加区别地将它们存储到同一文件组。
这样,不但会造成I/O竞争,也为数据库的维护工作带来不变。
2、组合索引的使用
假设存在组合索引it1c1c2(c1,c2),查询语句select * from t1 where c1=1 and c2=2能够使用该索引。
查询语句select * from t1 where c1=1也能够使用该索引。
但是,查询语句select * from t1 where c2=2不能够使用该索引,因为没有组合索引的引导列,即,要想使用c2列进行查找,必需出现c1等于某值。
根据where条件的不同,归纳如下:
1) c1=1 and c2=2:使用索引it1c1c2进行等值查找。
2) c1=1 and c2>2:使用索引it1c1c2进行范围查找,可以有两种方法。
方法1,使用通过索引键(1,2)在B树中命中一条记录,然后向后扫描找出第一条符合条件的记录,从此记录往后的每一条记录都是符合条件的。
这种方法的弊端在于:如果c1=1 and c2=2对应的记录数很多,会产生很多无效的扫描。
方法2,如果c2对应的int型数据,可以使用索引键(1,3)在B树中命中一条记录,从此记录往后的每一条记录都是符合条件的。
本文中的例子均采用方法1。
3)c1>1 and c2=2:因为索引的第一个列不是等于号的,索引即使后面出现了
c2=2,也不能将c2=2应用于索引查找。
这里,通过索引键(1,- ∞)在B树中命中一条记录,向后扫描找出第一条符合c1>1的记录,此后的每一条记录判断是
否符合c2=2,如果符合则输出,否则过滤掉。
这里我们称c2=2没有参与到索引运算中去。
这种情况在实际应用中经常出现。
4)c1>1:通过索引键(1,- ∞) 在B树中命中一条记录,以此向后扫描找出第一条符合c1>1的记录,此后的每条记录都是符合条件的。
3、唯一索引与非唯一索引的差异
假设索引int1c1(c1)是唯一索引,对于查询语句select c1 from t1 where c1=1,达梦数据库使用索引键(1)命中B树中一条记录,命中之后直接返回该记录(因为是唯一索引,所以最多只能有一条c1=1的记录)。
假设索引it1c2(c2)是非唯一索引,对于查询语句select c2 from t2 where c2=2,达梦数据库使用索引键(2)命中B树中一条记录,返回该记录,并继续向后扫描,如果该记录是满足c=2,返回该记录,继续扫描,直到遇到第一条不符合条件c2=2的记录。
于是,我们可以得知,对于不存在重复值的列,创建唯一索引优于创建非唯一索引。
4、非聚集索引的作用
每张表只可能一个聚集索引,聚集索引用来组织真实数据。
语句“create table employee (id int cluster primary key,name varchar(20),addr
varchar(20))”。
表employee的数据用id来组织。
如果要查找id=1000的员工记录,只要用索引键(1000)命中该聚集索引。
但是,对于要查找name=’张三’的员工记录就不能使用该索引了,需要进行全表扫描,对于每一条记录判断是否满足name=’张三’,这样会导致查询效率非常低。
要使用聚集索引,必需提供id,我们只能提供name,于是需要引入一个辅助结构实现name到id的转换,这就是非聚集索引的作用。
该非聚集索引的键是name,值是id。
于是语句“select * from employee where name=’张三’”的执行流程是:通过键(’张三’)命中非聚集索引,得到对应的id值3(假设’张三’对应的id为3),然后用键(3)命中聚集索引,得到相应的记录。
5、是不是使用非聚集索引的查询都需要进行聚集的查询?
不是的,虽然在上一点中查询转换为聚集索引的查找,有时候可以只需要使用非聚集索引。
创建表并创建相应的索引:create table t1(c1 int,c2 int,c3 int);create index it1c2c3 on t1(c2,c3)。
查询语句为:select c3 from t1 where c2=1。
因为索引it1c2c3(c2,c3)覆盖查询语句中的列(c2,c3)。
所以,该查询语句的执行流程为:通过索引键(1,- ∞)命中索引it1c2c3,对于该记录直接返回c3对应的值,继续向后扫描,如果索引记录中c1还是等于1,那么输出c3,以此类推,直到出现第一条c1不等于1的索引记录,结束查询。
6、创建索引的规则
创建索引首先要考虑的是列的可选择性。
比较一下列中唯一键的数量和表中记录的行数,就可以判断该列的可选择性。
如果该列的“唯一键的数量/表中记录行数”的比值越接近于1,则该列的可选择行越高。
在可选择性高的列上进行查询,返回的数据就较少,比较适合索引查询。
相反,比如性别列上只有两个值,可选择行就很小,不适合索引查询。
面试时,经常被问及“数据库调优”的事情,心想这不是DBA的事吗,但回答不好还是显得不够专业,查一下资料,许多还真是程序员的事情,下面总结一下,希望对大家有所帮助。
方面
以影响程度排序
D1 业务逻辑(影响最大)
D2 数据设计(表结构设计,数据建模)
D3 应用程序设计(SQL 语句的写法)
D4 数据库的逻辑结构(索引,区间,段,表空间)
D5 数据库操作(参数和配置)
D6 访问路径
D7 内存分配情况
D8 I/O 和物理设计(DBA 与业务沟通)(峰值多大,使用周期)
D9 资源的征用
D10 操作系统的调节
D1-D3 影响最大但比较难修改(事先去做)
D4-D9 性能影响不是最大但经常去做的(DBA)
D10 手段不是很多
可以看出D1-D3都是和程序员相关的,这也正合我以前的想法------良好的程序,业务逻辑设计是最好的调优。
其他的数据库系统都为我们做的差不多了。