1.1. 名词概述:
软件线程:每个运行的程序都是一个进程,每一个进程都会创建一个或多个线程,这些线程称之为软件线程。一个进程至少有一个线程,称为主线程。
硬件线程:也称之为逻辑内核或逻辑处理器,每一个硬件线程为一个可调度的逻辑处理器,每一个逻辑处理器可以运行软件线程的代码,windows调度器可以决定将一个软件线程赋给一个硬件线程,通过这种方式均衡每一个硬件线程的工作负载,以达到并行优化的作用。
SMP:SMP(Symmetric Multi-Processing),对称多处理结构的简称,是指在一个计算机上汇集了一组处理器(多CPU),各CPU之间共享内存子系统以及总线结构。在这种技术的支持下,一个服务器系统可以同时运行多个处理器,并共享内存和其他的主机资源。
CMT:(Chip Multithreading,芯片多线程)充分利用系统所有资源,不受应用设计,JVM垃圾收集,锁竞争,网络和磁盘IO等限制的应用。
NUMA系统:NUMA(Non Uniform Memory Access Architecture)技术可以使众多服务器像单一系统那样运转,同时保留小系统便于编程和管理的优点。非统一内存访问(NUMA)是一种用于多处理器的电脑记忆体设计,内存访问时间取决于处理器的内存位置。
QoS:QoS(Quality of Service,服务质量)指一个网络能够利用各种基础技术,为指定的网络通信提供更好的服务能力, 是网络的一种安全机制, 是用来解决网络延迟和阻塞等问题的一种技术。 在正常情况下,如果网络只用于特定的无时间限制的应用系统,并不需要QoS,比如Web应用,或E-mail设置等。但是对关键应用和多媒体应用就十分必要。当网络过载或拥塞时,QoS 能确保重要业务量不受延迟或丢弃,同时保证网络的高效运行。
应用的扩展模式:主要分为两种,垂直和水平,垂直扩展是指单个应用实例可以充分利用增加的CPU和内存资源,从而满足需求的增长。水平扩展是指在已有系统或者添加的硬件节点上增加应用实例,以此满足客户需求的增长,即在更多的系统上部署更多的应用实例,通常在多个系统面前部署负载均衡器,将负载分摊到不同应用实例上。
SUT(System Under Test):被测系统
1.2. 方法论
性能分析的两种方法:自顶向下,自底向上
自顶向下:自顶向下时,通常会从干系人发现性能问题的负载开始监控应用,应用的配置变化和日常负荷变化都可能导致性能降低,所有要持续监控应用。不管何种原因引起的性能调优,自顶向下的第一步总是对运行在特定负载之下的应用进行监控,范围包括操作系统,Java虚拟机,JavaEE容器以及应用的性能测量统计指标。
自底向上:在不同平台(指底层的CPU架构或CPU数量同)上进行应用调优时,通常使用自底向上的方法,自底向上关注的通常是在不更改应用的前提下,改善CPU使用率,假如应用可以更改,也能为如何修改应用提供建议;自底向上需要收集和监控最底层CPU的性能统计数据;监控的CPU统计数据包括执行特定任务所需要的CPU指令数,以及应用在一定负载下运行时的CPU高速缓存为命中率。
1.3. 操作系统性能监控
改善性能涉及3种不同的活动:性能监控,性能分析,性能调优。
性能监控:性能监控是一种以非侵入方式收集或查看应用运行性能数据的活动。
性能分析:相对于性能监控,性能分析是一种以侵入方式收集运行性能数据的活动,它会影响应用的吞吐量或响应行。
性能调优:相对于性能监控和分析,性能调优是一种为改善应用响应性或吞吐量而更改参数,源代码或属性的活动。
CPU使用率
大多数操作系统的CPU使用率分为用户态CPU使用率和系统态CPU使用率:用户态CPU使用率是指执行应用程序代码的时间占总CPU时间的百分比;系统态CPU使用率是指应用执行操作系统调用的时间占总CPU时间的百分比,系统态CPU使用率理想情况下的使用率为0%,所以提高应用性能和扩展的一个目标就是尽可能降低系统态CPU使用率。
监控CPU使用率工具:
Windows:Task Manager(任务管理器)和 performance Monitor (性能监视器)
命令行监控CPU使用率:Linux
1, vmstat [-s] 显示所有虚拟处理器的总CPU使用率 -s 间隔时间 vmstat 1
2, mpstat 以列表的方式展示每个虚拟处理器的CPU使用率
3, top 比较常用命令显示整个系统和进程信息包括CPU使用率,进程统计数和内存使用率
CPU调度程序运行队列
运行队列就是那些已经准备好运行,正等待可用CPU的轻量级进程,如果准备运行的轻量级进程数超过系统所能处理的上限,运行队列就会很长,系统运行队列长度等于虚拟处理器的个数时,用户不会明显感觉到性能下降,此处虚拟处理器个数就是系统硬件线程的个数,也是Java API Runtime.availableProcessrs()的返回值。当运行队列长度达虚拟处理的4倍或更多时,系统的响应就非常迟缓了。
解决运行队列长有两种方法:1,增加CPU以分担负载或减少处理器的负载量。2,改进CPU使用率,如减少垃圾收集的频度或采用同样任务但CPU指令更少的算法。
监控CPU调度程序运行队列:Linux 可使用 vmstat命令 输出r列 即为运行队列.
监控内存使用率命令:vmstat 输出的free列 关注 si和so列 分别表示内存页面换入和换出的量或使用top命令或/proc/meminfo文件监控
监控锁竞争:linux上可以使用sysstat包中的pidstat命令监控锁竞争(内核2.6.23以上)
Pidstat -w 输出结果中的csech/s是让步式上下文切换。让步式上下文切换浪费的时钟周期可以由pidstat -w的让步式上下文切换数除以虚拟处理器的数目得出,让步式上下文切换数乘以80000除以CPU每秒的时钟周期,可以得出让部式上下文切换所消费的CPU时钟周期百分比 示例:pidstat -w 每5秒监控进程id为9391的java 应用
$pidstat -w -I -p 9391 5
08:57:19 AM PID cswch/s Command
08:57:19 AM 9391 3500 java
处理器为3.0GHz 双核Intel CPU, pidstat 显示系统每秒大约发生3500个上下文切换,因此每个虚拟处理器的上下文切换为3500/2=1750 耗费的时钟周期为1750*80000=140 000 000.3GHz cpu每秒的时钟周期数为3 000 000 000 因此上下文切换所浪费的时钟周期为140 000 000 / 3 000 000 000 =4.7% 应用一般性准则(让步时钟周期占用3%~5%或更多),说明java应用正面临锁竞争。
监控网络I/O使用率和系统态CPU使用率:iostat -xm 5
1.4. JVM概述
HotSpot VM 基本架构
HotSpot VM 有3个主要组件:VM运行时(Runtime)JIT编译器(JIT Compiler) 以及内存管理器(Memory Manager )
JIT编译器:client | server
内存管理器:Serial Throughput CMS 或G1
早期HotSpot VM 是32位 JVM 内存地址空间限制为4G 随着服务器系统的内存越来越大,64位HotSpot应运行而生。
HotSpot VM 垃圾收集器
Java虚拟机(JVM)规范要求所有JVM的具体实现必须包括能够回收闲置内存的垃圾收集器;垃圾收集器的运行方式和执行效率对应用的性能和响应性有极大影响。
分代垃圾收集:
HotSpot VM 使用分代垃圾收集器基于以下两个观察
1,大多数分配对象的存活时间很短。
2,存活时间久的对象很少引用存活时间短的对象。
上述两个观察事实统称为弱分代假设,将Java应用而言,这个假设通常成立,基于此假设,HotSpotVM将堆分成2个物理区(也称为空间),这就是分代。
新生代:大多数新创建的对象被分配在新生代中,与整个Java堆相比,通常新生代的空间比较小而且收集频繁。新生代中大部分对象的存活时间很短,所以通常来说新生代收集(也成为次要垃圾收集,即Minor GC)之后存活的对象很少,因为MinorGC关注小并且有大量垃圾对象的通奸,所以通常垃圾收集的效率很高。
老年代:新生代中长期存活的对象最后被提升或晋升到老年代,通常,老年代比新生代大,而空间占用的增长速度比新生代慢,相比MinorGC而言,老年代收集(也称为主要垃圾收集或完全垃圾收集 FULL GC)的执行效率比较低,但是一但发生,执行时间比较长。
永久代:这是HopSpotVM内存中的第三块区域,虽称为代,但实际上不应用把它当作分代层的一部分(也就是说,用户程序 创建的对象最终并不会从老年代移送到永久代)相反,HotSpotVM只是用它来存储元数据,例如类的数据结构,保留字符串等。
Client JIT 和Server JIT 编译器概览
Client JIT 编译器的目标是为了更快的启动时间以及快速编译,使人不会为了应用的响应时间而纠结。
Server JIT 编译器的目标是使Java应用的性能达到极致,吞吐量也达到最高,所以它的设计焦点就是不遗余力的进行优化
垃圾收集
垃圾收集的重要数据
1,当前使用的垃圾收集器
2,Java堆的大小;
3,新生代和老年代的大小;
4,永久代的大小;
5,MinorGC的持续时间;
6,MinorGC的频率
7,MinorGC的空间回收量;
8,FullGC的持续时间;
9,FullGC的频繁率;
10,每个并发垃圾收集周期内的空间回收量;
11,垃圾回收前后新生代和老年代的占用量;
12,垃圾收集前后永久代的占用量;
13,是否老年代或永久代的占用触发了Full GC;
14,应用是否显示调用了System.GC()
Java应用性能分析技巧性能优化机会
1,使用更高效的算法
java基础及性能优化2,减少锁竞争
3,为算法生成更有效的代码
1.5. JVM性能调优入门方法
应用程序的性能需求了解
假设条件逐步展开的调优过程中,我们假设应用程序的执行遵循下面几个阶段初始化阶段
应用程序在这个阶段中初始化重要的数据结构及其他必要的组件
稳定态阶段
应用程序在这个阶段消耗了大多数的时间,核心的函数都在这个阶段中执行
总结阶段(可选)
总结性的工作在这个阶段进行,例如生产报告等。
应用程序在稳定态阶段消耗的执行时间最长,因此也是最关注的阶段。
应用程序的系统需求
可用性
可管理性
吞吐量
延迟及响应性
内存占用
启动时间
选择JVM部署模式
单JVM部署模式
多JVM部署模式
实际上并不存在“最好”的JVM部署模式,根据系统需求(譬如可用性,可管理性等)选择最合适的JVM部署方式才是最重要的
选择JVM运行模式
Client模式或Server模式
垃圾收集调优基础
性能属性:
吞吐量
延迟
内存占用,垃圾收集器流畅运行所需要的内存数量
原则
JVM垃圾收集器调优三个基本原则的理解
1,每次Minor GC都尽可能多地收集垃圾对象,我们称为“MinorGC回收原则”
2,处理吞吐量和延迟问题时,垃圾处理器能使用的内存越大,即Java堆空间越大,垃圾收集的效果越好,应用程序运行也越流畅,我们称之为“GC内存最大化原则”。
3,在这三个性能属性(吞吐量,延迟,内存占用)中任意选择两个进行JVM垃圾收集器调优。我们称之为“GC调优的3选2原则”
确定内存占用
约束
HotSpotVM堆的布局
堆大小调优着眼点
计算活跃数据大小
初始堆空间大小配置
Java堆大小计算法则
空间
命令行选项
占用倍数
Java堆
-Xms和-Xmx
3-4FullGC后的老年代空间占用量
永久代
-XX:PermSize
-XX:MaxPermSize
1.2-1.5倍FullGC后的永久代空间占用量
新生代
-Xmn
1-1.5倍FullGC后的老年代空间占用量
老年代
Java堆大小减新生代大小
2-3倍FullGC后的老年代空间占用量
调优延迟/响应性
评估垃圾收集器对延迟性影响的过程将进行下面的活动
测量MinorGC的持续时间;
统计MinorGC的次数
测量FullGC的最差(最长)持续时间
统计最差情况下,FullGC的频率
优化新生代的大小
调整新生代空间时,需要谨记下面几个准则
1,老年代空间大小不应该小于活跃数据大小的1.5倍
2,新生代空间至少应为Java堆大小的10%,通过-Xmx和-Xmd可以设定该值。
3,增大Java堆大小时,需要注意不要超过JVM可用的物理内存数。
优化老年代的大小
为CMS调优延迟
应尽量避免用尽老年代空间是非常重要的,从Throughput收集器迁移到CMS收集器时需要遵守一个通用原则是,将老年代空间增大20%-30%,这样才能有效运行CMS收集器,
调优CMS时,需关注几点
1,对象从新生代提升至老年代的速率
2,并行老年代垃圾收集线程回收空间的速率;
3,由于CMS收集器回收位于对象之间的垃圾对象而造成老年代空间的碎片化。
Survivor空间介绍
Survivor空间是新生代空间的一部分,计算Survivor计算公式如下:
Survivor size = -Xmn<value>/(-XX:SurvivorRatio=<ratio>+2)
解析晋升阈值
晋升阈值就是对象的年龄
监控晋升阈值
可监控晋升的分布或者对象年龄分布,并以此已经确定最优的最大晋升阈值
使用-XX:+PrintTenuringDistribution 可输出相关日志
调整Survivor空间的容量
初始化CMS收集周期
成功的CMS收集器调优要能以对象从新生代提升到老年代的同等速度对老年中的对象进行垃圾收集。达不到这个标准则称之为“失速”(lsot the race)失速的结果就会发生stop-the-world压缩式垃圾收集。避免失速的关键是要结合足够大的老年代空间和足够快的初始化CMS垃圾收集周期,让它以比提升速率更快的速度回收空间。
显式的垃圾收集
如果观察到由显式调用System.GC()触发的FullGC有两种处理方法
1,-XX:+ExplicitGCInvokesConcurrent或
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses(建议该使用选择)
2,-XX:+DisableExplicitGC
并发永久代垃圾收集
FullGC也可能源于永久代空间用尽。
调优CMS停顿时间
可以通过开启控制重新标记阶段使用的线程数
-XX:ParalleGCThreads=<n>
公式:
从Java6Update23开始,如果Java API Runtime.availableProcessors()的返回值小于等于8,默认值等于这个值,否则默认为 8+(Runtime.availableProcessors()-8)*5/8
应用程序吞吐量调优
CMS吞吐量调优
1,增加新生代空间大小
2,增加老年代空间大小
3,进一步优化新生代堆大小
4,进一步优化CMS周期的启动条件
Throughput收集器调优
对T怀柔ghput收集器惊喜吞吐量性能调优的目标是尽可能避免发生FullGC,或者更理想的情况下在稳定态时永不发生FullGC。为了达到这个目标需要优化对象老化频率,通过显式地微调Survivor空间可实现对象老化的优化
Throughput默认启用称之为自适应大小调整的特性,对于大多数应用自适应调优已经够用,如果要达到更高指标,可禁用自适应大小调整,对新生代进行细粒度调优
Survior空间调优
调优并行垃圾收集线程
其他行命令行选项
逃逸分析
逃逸分析是一种评估Java对象可见范围的技术,是指由某个执行线程创建的Java对象在另一个线程中可以访问,此时我们称该对象“逃逸”了
可以通过 -XX:+DoEscapeAnalysis 开启
偏向锁
偏向锁是一种偏向于最后获得对象锁的线程的优化技术
大页面支持
应用服务器监控
在典型的多层企业级应用部署中,客户端,应用服务器实例,数据库以及应用以来的外部系统会部署在不同的系统中。每个系统都会影响应用的整体性能。
监控操作系统属性通常包括:CPU,内核和用户内存使用率以及网络和磁盘I/O使用率。
JVM需要监控:垃圾收集,锁竞争和类装载。
1.6. Web应用的性能调优
Web容器的组件
GlassFish的部署基于域管理服务器所控制的若干个域,一个域可以包含若干个集群,一个集群是一个服务器实例组,每个组有若干个独立的服务器实例。
容器由一组嵌套的组件所构成。服务器包含若干个连接器,他们共享一个引擎组件。引擎包括若干个虚拟机,每个虚拟主机又包括若干个应用环境(Context)。每个应用里是Java Servlet和JSP.
HTTP连接器
GlassFish Web 容器使用Grizzly(NIO框架)这个框架可以扩展服务器以支持大量并发客户端。Grizzly的入口点是Selector模块,在这里创建NIO Selector .Selector线程池允许多个并行的Selector,扩展性更好。
处了基于NIO的Grizzly连接器,GlassFish还支持称为Coyote的阻塞式连接器,阻塞式连接器基于Java I/O,遵循每请求一线程的模型,处理来自单客户端的多个请求时,阻塞式可以工作的很好。但是每个打开的连接专用一个线程会导致扩展性问题,因此连接器通常最多处理几千个连接,这个问题在用户发起请求的速度比较慢时特别突出,这种情况下,因为缺少可用的处理线程,即便服务器的计算能力还有余量,服务器也不得不拒绝新的连接。
由于基于NIO的连接器用有限的工作线程处理所有连接,所以它可能扩展到几千个连接,GlassFish的性能测试显示,它能处理的连接超过1W个。
Servlet引擎
连接器将请求传递给Servlet引擎以便进一步处理。多个连接器共享一个引擎,引擎由多个嵌套的组件构成,最外层是一个或多个虚拟主机。
Web容器的监控和性能调优
容器的开发和生产模式
Web容器支持两种不同的模式----开发模式和生产模式,两种模式下,容器处理已部署JSP页面发生变动的方式有所不同。
开发模式下,JSP自动重新加载,容器会检查每个页面,看是否有任何变化。生产模式下,自动重新加载是关闭的,想要应用的任何修改可见,需要重新部署。默认情况下开发者配置下的GlassFish会把容器设置成开发模式。。生产模式建议关闭自动重新加载。
安全管理器
Java安全管理器负责安全策略的管理,决定代码是否有权访问受保护的资源。GlassFish中Java安全管理器默认为关闭,开启安全管理器会影响所有部署在该应用服务器实例上应用。
JVM调优
Web容器性能调优最重要的一项是对运行容器的JVM进行调优
HTTP监听器
http监听器可以提供连接队列,线程池,文件缓存和keep-alive的数据
Asadmin list -m “server.*http-listener-1.*” 显示http-listener-1可监控元素
1,线程池
线程池的线程数设置
属性
初始值
属性
初始值
初始线程数
硬件线程数
线程数
2×硬件线程数
线程池调优技巧
属性
描述
调优技巧
Maxthreads-count
线程池允许的最大线程数
依据CPU使用率和currentthreadsbusy-count调整改值。如果所有线程持续被占用而CPU资源仍然可用,增加该值。池大小设置过高会性能有不利影响,因为增加了上下文切换,CPU高速缓存为命中等
Currentthreadsbusy-count
当前在监听器线程池中正用于处理请求的线程数
如果该值一直等于maxthreads-count,意味着系统负载足够,处理请求的线程被充分利用。
适当的对HTTP请求的线程池调优,对获得**性能来说非常重要,http-service。Request-processing.thread-count比较好的初始值是,非CMT类型的CPU时,为核数的2倍,而CMT类型的CPU时为虚拟处理器数的2倍,需监控currentthreadsbusy-count以验证有效性。
2,Acceptor线程,连接队列和keep-alive
Asadmin get “configs.config.server-config.*tcp.*”获取Acceptor-threads默认值
Asadmin get -m “server.network.http-listener-1*connection-queue.*” 通过GlassFish监控框架获得各种连接队列的统计数据
Asadmin get -m server.network.http-listener-1.keep-alive.* 获取keep-alive默认值。
Acceptor-threas是Seletor线程数。由于seletor线程为服务器处理读请求任务,而服务器需要处理大量连接,所以默认一个线程是不够的,建议设置该值等于系统处理器的数目
Acceptor线程调优技巧
属性
描述
调优技巧
Acceptor-threads
Selector线程
对于多处理器系统而言,该值可设置为可用的处理器数。
连接队列调优技巧
属性
描述
说明
Countqueued-count
当前队列中的连接数
当处理线程可用时,会处理队列中的请求。如果该值一直很大,说明系统负载很高,线程池优化不到位或应用中存在锁竞争
Countqueued*minuteaverage-count
最近1,5或15分钟内平均的排队连接数
可以过滤出短期负债的峰值
Countoverflows-count
因队列满而拒绝连接的次数
拒绝客户端连接会导致糟糕的用户体验,如果客户端可以忍受更长的响应时间,增加队列长度可以减少连接拒绝的次数,高负载系统可以采用的解决方案是垂直扩展或水平扩展应用服务器层。
Keep-alive调优技巧
属性
描述
说明
Countconnections-count
Keep-alive模式下的连接数
如果值一直偏高(每核几百个)可以考虑减少最大请求数或缩短超时时间
Counthits-count
命中缓存的次数
命中率(keep-alive.counthits-count/request.countrequests-count)高,说明当前设置运转良好
Countrefusals-count
因超出每个连接最大请求数而被拒绝的keep-alive连接数
Keep-alive.max-requests可以限制每个连接的请求数,客户端必须为后续的请求开启新连接。如果HTTP连接器以阻塞式方式运行,建议保留默认值。当HTTP连接器运行在非阻塞模式或可信客户端时,可以设置为-1(意味着请求数不受限制)
Counnttimeouts-count
已经超时的keep-alive连接数
Keep-alive默认为30秒,如果返回客户端花费的时间多数超过该范围,可以提供该值,如果该值很大,会导致许多不必要存活的连接从而降低性能。
HTTP/1.1默认使用持久化连接,一个连接中客户端可以发起多个请求,服务器维护keep-alive的连接,使得用户代理可以在同一个连接中连续发起请求,而不用每个请求都创建一个连接(http/1.0)。如果符合下列某个条件,服务器则关闭连接
1,当前请求与上一个之间的流逝时间超过timeout-in-seconds
2,一个连接中请求数超过max-connections
当使用Coytor阻塞式连接器时,max-connections可以防止恶意客户端无限制霸占线程。如果实例使用Grizzly NIO连接器或者实例只有可信客户端才能访问,那就可以取消这个限制,设置为-1即可。
3,请求处理
Asadmin get -m “server.http-service.server.request.*” | grep ‘count.*-count’ 获取所处理请求的各种指标。
响应代码及说明
属性
描述
说明
Countrequests-count
自服务器启动以来处理的请求总数
Count200-count
状态码为200 OK的响应数
Count200-count/Countrequests-count 表示正常处理的请求比例
Count302-count
重定向的请求数
重定向会产生两个浏览器请求而不是一个
Count304-count
上次访问之后资源没有变化的请求数
这类响应所占的比例大说明可能需要资源缓存。也已可以通过设置适当的HTTP缓存首部减少这个请求
Count404-count
服务器无法找到与URL匹配的资源的次数
这个值高表示应用内部有不正确的资源引用,需要纠正
Count5xx-count
服务器错误的报告次数
对于健康的应用来说,这个值应为为0
Count200-count
4.应用程序
将Web容器的监控级别设为LOW或HIGH 就能获取各个应用的性能统计数据
Asadmin set server.monitoring-service.module-monitoring-levels.web-container=LOW
和EJB容器不同,web容器的LOW和HIGH在显示输出上没有什么差别。
监控框架提供了各种应用级别的统计数据:
Asadmin list -m “server.Applications.TestWebApp*”
Asadmin get -m
其他优化
HTTP压缩
HTTP压缩有助于减少文本数据从服务器传送到客户端的大小。
Asadmin get “config.config.server-config.network-config.protocols.protocol.http-listener-1.http.*” | grep compress 获取相关属性值
对于通过慢速网络连接的客户端,开启HTTP压缩可以减少页面的发送时间。
内容缓存
序列化和压缩技术在缓存解决方案的整体性能中,扮演了重要角色,建议用户星际试验,为每个组件找到最好的解决方案/实现
会话持久
为了性能最优,保存在会话中的条目应用小而简单。对于可以在会话恢复时重建的属性,最好使用关键字transient
HTTP服务器文件缓存
将http-service的监控级别设成too high可以监控文件缓存的统计信息。
Asadmin get -m “server*http-listener-1.file-cache*” | grep ‘-count’
依据经常被访问的文件数设置需要被缓存的文件数,多数情况下,默认值1024就足够了。
依据客户端访问特定资源的频度设置缓存文件的最大年龄,建议设置足够大,使文件缓存中移除前,能够命中若干次。
开启访问日志
Asadmin set config.configs.server-config.http-service.access-log.rotation-enabled=true
1.7. Web Servive的性能
面向服务的架构(SOA)是一种新型架构方式,它能通过分布在网络上的多个较小规模的单一服务构建复杂的业务应用。
XML的性能
1,XML处理的生命周期
2,解析/解编组
3,访问
4,修改
5,序列化/编组
验证
解析外部实体
选择合适的API
影响WebService性能的因素
1,消失大小的影响
2,不同Schema类型的性能特性
3,终端服务器的实现
4,处理程序的性能
**性能实践
1,二进制负载的处理
2,处理XML文档
3,使用MTOM发送XML文档
4,使用Provider接口
5,快速信息集
6,HTTP压缩
7,webService客户端的性能
1.8. Java持久化及Enterprise Java Bean的性能
EJB是一种基于组件的架构,适用于大型,分布式,面向事务的企业级应用。
监控及调优EJB容器
将EJB容器的监控级别设置成HIGH会导致严重的性能下降
线程池
用于处理EJB实例业务逻辑的线程池取决于调用模式。
远程EJB调用是由一个不同的线程池(ORB线程池)处理。
Asadmin get “server.thread-pools.thread-pool.thread-pool-1.*” 查看修改该值
Asadmin get -m “server.thread-pools.orb.threadpool.thread-pool-1.numberofavailablethreads-count”
“server.thread-pools.orb.threadpool.thread-pool-1.numberofworkitemsinqueue-current”
ORB线程池设置
属性
初始值
线程池的最小容量
硬件线程数或虚拟处理器的数目
线程池的最大容量
硬件线程数或虚拟处理器数目的两倍
调优线程池可监控的属性
属性
描述
调优提示
numberofavailablethreadscount
可用处理请求的线程数
如果该值一直为0,表明系统的负载已经大到足够耗尽线程池的程度
numberofworkitemsinqueuecurrent
等待处理的请求数
如果该值持续在高位,表明系统负载过高,或线程池需要进行调优,如果系统已经充分利用了CPU,就没必要进一步调优,如果仍有CPU资源空闲,而线程池中没有可以用于处理请求的线程,则需要增大线程池的容量。
Bean池和缓存
EJB容器使用各种池和缓存来提高服务器的性能
asadmin get server.ejb-container.* 列出不同EJB容器的属性
查看Bea池的统计信息
Asadmin get -m server.Application.SPECjAppServer.mfg_jar.LargeOrderSes.bean-pool.*count
EJB2.0
使用容器管理的事务还是使用Bean管理的事务
选择正确的事务属性
控制序列化
缓存静态资源引用
使用本地接口取代远程接口
粗粒度访问
使用延迟载入或预取载入
选择正确的数据库锁策略
EJB查询语言
只读实体Bean
对于值不会发生变化,或者可以忍受过期数据的实体,推荐使用只读实体Bean
EJB3.0
JPA查询语言中的查询
查询结果缓存
FetchType:FetchType设定了持久化组件从数据库中抓取数据的策略。
连接池
连接池容量值至少应该等于处理请求的线程数。
选择正确的数据库锁策略
不带事务的读取
Java持久化规范允许不使用事务执行只读的实体管理操作,当实体状态不发生修改时,推荐使用这种操作。
继承
Java持久化允许从另一个实体或非实体继承。
1.9. 重要的HotSpot VM选项
形式: -XX:<+|->FeatureName +表示开启,-表示关闭
形式:-XX:FeatureName=<n> n表示数字 k,m,g表示:KB,MB,GB 其他数字的选项则表示比率或百分比
HotSpot VM
参数
释义
-client
指示HotSpot VM 把应用当成客户端程序进行优化,将运行时环境设为client JVM ,此类应用,内存占用重要性能标准,远比高吞吐量重要。
-server
指示HotSpot VM 把应用当成服务器程序进行优化,将运行时环境设为server JVM ,此类应用适用于高吞吐量比启动时间和内存占用更重要的应用程序。
-d64
加载64位HotSpot VM而不是32的VM。 需要比32位HotSpotVM更大的Java堆时可以使用该选项,-Xmx和-Xms小于32GB时该选项要与-XX:+UseCompressedOops联合使用,Java Update23 之后HotSpot默认开启该参数。
-XX:+UseCompressedOops
开启压缩针特性,Java引用的长度从32位增加到64位,这给64位JVM带来了性能损失,长度的增加使得缓存行中可容纳的oops变少了,CPU高速缓存的效率也因此降低。64位JVM上CPU高速缓存效率的降低常常导致64位JVM的性能比32位降低8%-20%,开始该参数使得64位JVM不但有更大的堆而且还有32位JVM的性能,如果JVM堆上线不超过32GB(-Xmx32g)上限为26GB性能最好(-Xmx26g)
-Xms<n>[g|m|k]
Java初始堆初始和最小值,是新生代和老年代的总和,如果-Xms小于-Xmx,java堆的大小会依据应用的需要而扩展或缩减,Java堆的扩展或缩减需要FULL GC 所以注重延迟性或吞吐量性能的应用程序通常应把-Xms和-Xmx设置相同的值
-Xmx<n>[g|m|k]
Java堆最大值,是新生代和老年代的总和
-XX:NewSize=<n>[g|m|k]
新生代初始值,注重延迟或吞吐量性能的应用通常把-XX:NewSize和-XX:MaxNewSize设置相同的值
-XX:MaxNewSize=<n>[g|m|k]
新生代最大值
-Xmn<n>[g|m|k]
新生代初始,最小和最大值,如果期望将-XX:NewSize和-XX:MaxNewSize设置成相同的值,这是一个便利的命令选项。
-XX:NewRation=<n>
新生代和老年代的尺寸比,如n为3,则比率为1:3即新生代占新生代与老年代大小总和的1/4,如果-xms和-xmx不同,并且希望新生代和老年代的大小维持特定的比率时,这是个便利的命令。
-XX:PermSize=<n>[g|m|k]
永久代初始值,优化时通常将-XX:PermSize和-XX:MaxPermSiz值设置成相同
-XX:MaxPermSize=<n>[g|m|k]
永久代最大值
-XX:SurvivorRation=<n>
单块Survivor区与Eden区大小比率,计算公司为
Survivor Size=-Xmn<n>/(-XX:SurvivorRation=<n>+2)
指定的比率越大Survivor区的尺寸越小
+2是因为有两块SurvivorRation
-XX:InitialSurvivorRation=<n>
Survivor区初始比率应与Throughput收集器配合使用,n是比率。
-XX:TargetSurvivorRation=<percent>
在HostSpotVM Minor GC之后,Survivor区被占用的最大值,值是Sur区被占用的百分数,默认50%
-XX:+UseSerialGC
开启单线程,Stop-Thr-World的新生代和了老年代垃圾收集器,比较古老成熟的垃圾收集器,一般在JAVA堆比较小时(-xmx256或更小)时才使用
-XX:UserParallelGC
开启HotSpotVM的多线程,Stip-The-World的Throughput收集器,新生代使用多线程垃圾收集器,老年代使用单线程
-XX:+UseParalleloldGC
开启HotSpotVM多线程Throughput收集器,新生代和老年代都是多线程垃圾收集器。
-XX:-UseAdaptiveSizePolicy
关闭自适应调整新生代Eden区和Survivor区尺寸的特性,只有Throughput收集器支持自适应尺寸调整,开启或关闭该属性在CMS和Serial收集器不起作用
-XX:+UseConcMarkSweepGC
开启HotSpotVM的CMS收集器,它会自动开启-XX:+UseParNewGC,新生代使用多线程垃圾收集器,老年代使用CMS收集器。
-XX:+UseParNeGC
开启多线程,Stop-the-World的新生代垃圾收集器,需要配合以并发为主的老年代垃圾收集器CMS
-XX:ParallelGCThreads=<n>
控制多线程垃圾收集器收集线程并行数,<n>是运行的线程数,从Java6Update23后,Runtime.availableProcessors()值大于8计算公式:8+(Runtime.availableProcessors()-8)*5/8
-XX:MaxTenuringThreshold=<n>
设置最大晋升阈值,这个值作用于对象的最大年龄,它会将达到这个阈值的对象从新生代提升到老年代,使用CMS收集器时,为了使对象老化的算法更有效,可使用该参数。
-XX:CMSInitiatingOccupancyFraction=<percent>
老年代占用达到该百分比时就会引发CMS的第一次垃圾收集周期,如果还设定了-XX:UseCMSInitiatingOccupancyOnly则每次老年代占用达到该百分比时就会开始CMS的垃圾收集周期,一般建议同时使用这两个参数。
-XX:UseCMSInitiatingOccupancyOnly
表示只有在老年代占用达到-XX:CMSInitiatingOccupancyFraction=设定的值时,才会引发CMS的并发垃圾收集周期。
-XX:CMSInitiatingPermOccupFraction=<percent>
永久代占用达到该百分比时,就会引发CMS的第一次垃圾收集周期,一般来说建议同时和-XX:+UseCMSInitiatingOccupancyOnly使用。
-XX:+CMSClassUnloadingEnabled
开启永久代并发垃圾收集,希望永久代使用CMS进行垃圾收集时开启该参数,如果使用JAVA6Update3或更早的JDK还需要开启-XX:+CMSPermGenSweepingEnabled.
-XX:+CMSPermGenSweepingEnabled
开启永久代的CMS垃圾清除。
-XX:+CMSScavengeBeforeRemark
指示HotSpotVM在执行CMS重新标记之前进行MinorGC
-XX:+ScavengeBeforeFullGC
开启-XX:UseParallelGC或-XX:+UseParallelOldGC的情况下指示HotSpotVM在执行FullGC之前,进行MinorGC
-XX:ParalleRefProcEnabled
开启多线程引用处理,这个选项可以缩短HotSpotVM处理Reference对象和finalizer所花费的时间。
-XX:+ExplictGCInvokesConcurrent
请求HotSpotVM显示地并发执行GC也就是System.GC()调用。一般来说建议使用-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses,而不是该参数
除了是从永久代卸载类以外与-XX:+ExplictGCInvokesConcurrent相同
-XX:+DisableExplicitGC
禁止因显示调用System.GC()而引起的Full GC
-XX:+CMSIncrementalMode
开启增量式CMS收集器,即CMS的并发阶段为增量方式,定期暂停并发,将处理器让步给应用线程,一般不建议在多核系统或者JAVA堆比较大时使用。
-XX:+CMSIncrementalPacing
允许增量式CMS收集器在放弃处理器前,依据应用程序行为,自动控制工作量,只能与-XX:+CMSIncrementalMode一起用。
-verbose:GC
报告每次垃圾收集时的基本GC信息。建议使用-XX:PrintGCDetails而不是-verbose:GC
-XX:+PrintGC
报告每次 垃圾收集时的基本GC信息建议使用-XX:PrintGCDetails
-XlogGC:<filename>
将垃圾收集的统计信息打印到文件中。
-XX:+PrintGCDetails
开启新生代,老年代和永久代垃圾收集统计信息的详细报告
-XX:+PrintGCTimeStamps
在每次垃圾收集时打印时间戳,指示自JVM启动以来的流逝时间
-XX:+PrintGCDateStamps
在每次垃圾收集时打印本地日期时间戳
-XX:+PrintTenuringDistribution
报告与对象晋升相关的统计数据,包括Survivor区的占用量以免过早将对象从Survivor提升到老年代
-XX:+PrintAdaptiveSizePolicy
报告Throughput收集器GC的详细统计信息
-XX:+PrintGCApplicationStoppedTime
打印有HotSpotVM内部操作使得应用线程停止所持续的时间
-XX:+PrintGCApplicationConcurrentTime
打印应用线程随HotSpotVM内部线程并发执行所用的时间。
-XX:+PrintSafepointStatistics
打印VM已经发生的安全点操作和发生的时间
-XX:+BackgroundCompilation
指示JIT编译器作为后台任务运行,以解释模式运行方法知道后台编译完成,VM默认开启
-Xbatch
关闭JIT编译器的后台编译等价于-XX:+BackgroundCompilation
-XX:TieredCompilation
开启JIT编译策略,显示进行快速的JIT编译,该策略汲取了-client和-server运行时环境,结合评估实际应用的启动和相应能力,采取适合策略。
-XX:+PrintCompilation
打印VM JIT编译器优化过的所有方法的JIT编译信息。
-XX:+PrintInlining
报告已经或试图内联方法,以及方法字节码的字节长度
-XX:MaxInlineSize=<n>
除非有足够的证据,例如性能分析信息表明这个方法是热方法,否则字节码长度超出这个最大值的方法不会被内联。
-XX:+PrintOptoAssembly
打印HotSpot Server JIT编译器所作的优化决策,包括生成的汇编码
-XX:+HeapDumpOnOutOfMemoryError
在OutOfMemoryError发生时,生成JVM堆的转储文件。
-XX:HeapDumPath=<path>
设置堆转储文件的生成目录路径为<path>
-XX:OnOutOfMemoryError=<command or set of commands>
允许HotSpot遇到OutOfMemoryError时可以运行一个或者一组命令。
-XX:+ShowMessageBoxOnError
允许HotSpotVM推出前显示对话框(GUI)表明他遇到了致命错误。
-XX:OnError=<command or set of commands>
允许应用程序遇到HotSpotVM意外退出时调用一组命令
-Xcheck:jni
允许用了JNI的java程序使用另一组调试接口
-XX:+AggressiveOpts
允许使用最新的HotSpotVM性能优化。
-XX:+AggressiveHeap
建议使用-XX:+AggressiveOpts
-XX:+UseBiasedLocking
开启偏向锁特性,JAVA6默认自动开启
-XX:+DoEscapeAnalysis
开启逃逸分析的优化特性。随-XX:+AggressiveOpts开启自动开启
-XX:+UseLargePages
允许HotSpotVM使用大内存分页。使用该选项可以减少TLB(分页缓存)的未命中率
-XX:LargrPageSizeInBytes=<n>[g|m|k]
允许HotSpotVM指定大小的大内存分页,底层硬件平台必须支持<n>[g|m|k]大小的分页尺寸,否则就使用默认的分页尺寸。
-XX:+AlwaysPreTouch
VM在初始化时会提交所有内存分页,该选项强制VM在初始化过程中,触碰所有这些归JVM使用的内存分页。建议在开启-XX:+UseLargePages时开启该选项
-XX:+UseNUMA
开启(NUMA)java堆分配策略,在NUMA系统上,借助处理器和内存节点的关系,将对象分配在处理器本地的内存节点上,减少从内存获取数据的时间
NUMA(Non Uniform Memory Access Architecture)技术可以使众多服务器像单一系统那样运转,同时保留小系统便于编程和管理的优点
-XX:+PrintCommandLineFlags
打印HotSpotVM依据命令行设定选项经过自动优化之后的设置
-XX:+PrintFlagsFinal
打印所有product类型的HotSpotVM命令行选项。
GC 参数参考:http://unixboy.iteye.com/blog/
http://www.blogjava.net/killme2008/archive/2009/09/22/295931.html
http://pengjiaheng.iteye.com/blog/
http://blog.sina.com.cn/s/blog_4cb531010100w0uj.html
http://itlab.idcquan.com/Java/Jvm/876764.html
http://developer.51cto.com/art/201201/312018.htm#CMSInitiatingOccupancyFraction_value
http://www.2cto.com/kf/201302/187420.html
http://www.cnblogs.com/redcreen/archive/2011/05/04/2037029.html //collector种类
http://blog.csdn.net/huangzhaoyang2009/article/details/ //GC日志分析
http://www.open-open.com/lib/view/open1324736648468.html //详细说明
http://hllvm.group.iteye.com/group/topic/27945 //详细
http://www.360doc.com/content/13/0305/10/15643_269388816.shtml // GC专家优化策略
详细参数说明:
http://kenwublog.com/docs/java6-jvm-options-chinese-edition.htm
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
http://www.oracle.com/technetwork/java/GC-tuning-5-138395.html
监控脚本编写:
http://www.csdn.net/article/2012-06-26/
参考资料
Java6性能调优白皮书
http://java.sun.com/performance/reference/whitepapers/6_performance.html
Java6 GC调优指南
http://java.sun.com/javase/technologies/hotspot/GC/GC_tuning_6.html
更为全面的options列表
http://blogs.sun.com/watt/resource/jvm-options-list.html
JVM 选项全集:
http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp
http://iamzhongyong.iteye.com/blog/ //关乎GC回收不彻底
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/24673.html