首页 > 编程语言 >Java SE和Java EE应用的性能调优

Java SE和Java EE应用的性能调优

时间:2023-06-21 13:03:42浏览次数:44  
标签:底向上 Java 测试 EE 性能 调优 应用 CPU


凡事预则立,不预则废,和许多事情一样,Java性能调优的成功,离不开行动计划、方法或策略以及特定的领域背景知识。为了在Java性能调优工作中有所成就,你得超越“花似雾中看”的状态,进入“悠然见南山”或者已然是“一览众山小”的境界。

这三个境界的说法可能让你有些糊涂吧,下面进一步解释。

  • 花似雾中看(I don't know what I don't know)。有时候下达的任务会涉及你所不熟悉的问题域。理解陌生问题域首先面临的困难就是如何竭尽所能地学会它,因为你对它几乎一无所知。对于这类问题域,你有许多东西不了解,或者不知道重点。换句话说,这个问题域有哪些东西需要了解,你还傻傻看不清楚。这个阶段就是“花似雾中看”。
  • 悠然见南山(I know what I don't know)。刚进入不熟悉的问题域时,你对它知之甚少,随着时间的推移,你对它的许多重要方面都已有所认识,只是对重要的具体细节还缺乏了解。这时,你可以算是刚刚“见南山”。
  • 一览众山小(I already know what I need to know)。还有些时候,你对任务的问题域非常熟悉,或者已经具有该领域所必备的技能和知识,是这方面的专家。或者你对问题域足够了解,处理起来得心应手,比如你已经掌握了必要的知识,解决问题游刃有余。如果达到这个境界,那就意味着你已经是“一览众山小”了。

通常认为,传统的软件开发过程主要包括4个阶段:分析、设计、编码和测试,如图1-1所示。


图1-1 传统软件开发过程

替换图字: start:开始; analysis:分析; design:设计; code:编码; test:测试;
quality:质量合格?; yes:是; no:否; deploy:部署

分析是开发过程的第一步,用于评估需求、权衡各种架构的利弊以及构思高层抽象。设计则依据分析阶段的基本架构和高层抽象,进行更精细的抽象并着手考虑具体实现。编码自然就是设计的实现。编码之后是测试,用以验证实现是否合乎应用需求。值得注意的是,测试阶段通常只包括功能测试,即检验应用的执行是否合乎需求规格。一旦测试完成,应用就可以发布给客户了。

遵循这种传统软件开发过程的应用,通常要到测试或即将发布时才会关注性能或扩展性。为了解决这个问题,Wilson和Kesselman对传统软件开发过程做了些补充,在传统开发模型基础上引入了性能测试分析阶段,参见他们的畅销书Java Platform Performance。他们建议在测试阶段之后增加性能测试,并将“性能测试是否通过”设定为产品是否发布的标准。如果达到性能和扩展性标准,应用就可以发布,否则就要转向性能分析,并依据分析结果回到之前的某个或者某些步骤。换句话说,通过性能分析来定位性能问题。Wilson和Kesselman添加的性能测试分析如图1-2所示。


图1-2 Wilson和Kesselman添加性能测试分析之后的软件开发过程

替换图字: start:开始; analysis:分析; design:设计; code:编码; performance test:性能测试; performance acceptable:性能测试是否通过; profile:性能分析; yes:是; no:否; deploy:部署

对分析阶段提炼出来的性能需求,Wilson和Kesselman建议以用例(use case)的方式特别标识出来,这有助于在分析阶段制定性能评估指标。不过应用的需求文档中通常都不会明确描述性能或扩展性需求。如果你正在开发的应用还没有明确定义这些需求,那就应该想办法将它们挖掘出来。拿吞吐量和延迟性需求举例,以下清单列举了挖掘这些需求所要考虑的问题。

  • 应用预期的吞吐量是多少?
  • 请求和响应之间的延迟预期是多少?
  • 应用支持多少并发用户或者并发任务?
  • 当并发用户数或并发任务数达到最大时,可接受的吞吐量和延迟是多少?
  • 最差情况下的延迟是多少?
  • 要使垃圾收集引入的延迟在可容忍范围之内,垃圾收集的频率应该是多少?

需求和对应的用例文档应该回答上述问题,并以此制定基准测试和性能测试,确保应用能够满足性能和扩展性需求。基准测试和性能测试应该在性能测试阶段执行。评估用例时有些用例的风险过高,难以实现,应该在分析阶段后期,通过一些原型、基准测试和微基准测试来降低此类风险。分析结束后再变更决策的代价非常高,这个方法可以让你事先对决策进行评估。软件开发周期中的软件缺陷、低劣设计和糟糕实现发现得越晚,修复的代价就越大,这是一条颠扑不破的金科玉律。降低用例的高风险有助于避免这些代价昂贵的错误。

现在许多应用在开发过程中都会使用自动构建和测试。Wilson和Kesselman建议改进软件开发过程,在自动构建或测试中进一步添加自动性能测试。自动性能测试可以发出通知,比如用电子邮件将性能测试结果(如性能是衰减还是改善,或性能指标的达成度)发送给干系人。这个过程可以将因不满足应用性能指标而失败的测试,以及测试的统计数据自动记录到追踪系统。

将性能测试集成到自动构建过程中后,每次代码变更提交到源代码库时,都能很容易地追踪因变更而导致的性能变化,也就能在软件开发的早期发现性能衰减。

另外,将统计方法和自动统计分析添加到自动性能测试系统中也值得考虑。运用统计方法可以进一步验证性能测试的结果。


自顶向下和自底向上是两种常用的性能分析方法。顾名思义,自顶向下(Top Down)着眼于应用顶层,从上往下寻找软件栈中的优化机会和问题。相反,自底向上(Bottom Up)则从软件栈最底层的CPU统计数据(例如CPU缓存未命中率、CPU指令效率)开始,逐渐上升到应用自身的结构或该应用常见的使用方式。应用开发人员常常使用自顶向下的方法,而性能问题专家则通常采用自底向上的方法,用以辨别因不同硬件架构、操作系统或不同的Java虚拟机实现所导致的性能差异。如你所想,不同方法可以用来查找不同类型的性能问题。

自顶向下大概是最常用的性能调优方法。如果需要更改应用软件栈的顶层代码进行调优,这也是最常用的方法。

使用自顶向下的方法时,通常你需要从干系人发现性能问题的负载开始监控应用。应用的配置变化或日常负荷变化可能导致性能降低,这种情况下,需要持续地监控应用。此外,当应用的性能和扩展性需求发生变化时,应用可能无法满足新的要求,这时也需要监控应用程序的性能。

不管何种原因引起的性能调优,自顶向下的第一步总是对运行在特定负载之下的应用进行监控。监控的范围包括操作系统、Java虚拟机、Java EE容器以及应用的性能测量统计指标。基于监控信息所给出的提示再开展下一步工作,例如JVM垃圾收集器调优、JVM命令行参数调优、操作系统调优,或者应用程序性能分析。性能分析可能导致应用程序的更改,或者发现第三方库或Java SE类库在实现上的不足。

在不同平台(指底层的CPU架构和数量不同)上进行应用性能调优时,性能专家常使用自底向上的方法。将应用迁移到其他操作系统上时,也常用这种方法改善性能。在无法更改应用源代码时,例如应用已经部署在生产环境中,或者系统供应商为了在竞争中占得先机而必须将性能发挥到极致,也常常会使用这种方法。

自底向上需要收集和监控最底层CPU的性能统计数据。监控的CPU统计数据包括执行特定任务所需要的CPU指令数(通常称为路径长度,path length),以及应用在一定负载下运行时的CPU缓存未命中率。虽然还有其他重要的CPU统计数据,但这两项是自底向上中最常用的。在一定负载下,应用执行和扩展所需的CPU指令越少,运行得就越快。降低CPU缓存未命中率也能改善应用的性能,因为CPU缓存失效会导致CPU为了等待从内存获取数据而浪费若干个周期,而降低CPU缓存未命中率,意味着CPU可以减少等待内存数据的时间,应用也就能运行得更快。

自底向上关注的通常是在不更改应用的前提下,改善CPU使用率。假如应用可以更改,自底向上也能为如何修改应用提供建议。这些更改包括应用源代码的变动,如将经常使用的数据移到一起,使得访问同一条CPU缓存行(CPU cache line)就能获取这些数据,而不用等待从内存中获取数据。这个改动可以降低CPU缓存未命中率,从而减少CPU等待内存数据的时间。

现代Java虚拟机集成了成熟的JIT编译器,可以在Java应用的执行过程中进行优化,比如依据应用的内存访问模式或应用特定的代码路径,生成更有效的机器码。也可以调整操作系统的设置来改善性能,例如更改CPU调度算法,或者修改操作系统的等待时间(指操作系统在将应用执行线程迁移到其他CPU硬件线程之前所等待的时间)。

如果你觉得可以用自底向上的方法,那应该先从收集操作系统和JVM的统计数据开始。监控这些统计数据可以为下一步应该关注哪些重点提供线索。

本文内容摘自《 Java性能优化权威指南》



Java SE和Java EE应用的性能调优_性能测试

标签:底向上,Java,测试,EE,性能,调优,应用,CPU
From: https://blog.51cto.com/u_15767091/6528199

相关文章

  • Java乐观锁实现文章点击量、收藏计数、点赞计数
    Java乐观锁实现文章点击量、收藏计数、点赞计数......
  • 基于JAVA出差报销管理系统
    如今公司与企业规模不断扩大,出差管理在公司人事中的地位很重要。我们应该使用现代信息技术,研发基于Web技术的出差管理系统,这样可以节省人工管理成本,提高相关工作者的工作效率,推动公司与事业部的管理的信息化进程,进而进一步提升公司的核心竞争力。本文从公司/企业出差管理的实......
  • 智能家居ZigBee芯片CC2530F256RHAR内置单片机C8051内核
    CC2530结合了领先的RF收发器的优良性能,业界标准的增强型8051CPU,系统内可编程闪存,8-KBRAM和许多其它强大的功能。CC2530有四种不同的闪存版本:CC2530F32/64/128/256,分别具有32/64/128/256KB的闪存。CC2530具有不同的运行模式,使得它尤其适应超低功耗要求的系统。运行模式之......
  • Java学习之注册中心Zookeeper
    Zookeeper是什么ZooKeeper是一个用于维护配置信息、命名、提供分布式同步和提供组服务的集中式服务,它常作为一个注册中心服务用于分布式项目。Zookeeper拥有以下几个重要特性顺序一致性:来自客户端的相关指令会按照顺序执行,不会出现乱序的情况,客户端发送到服务的指令1->2->3->4,......
  • 【Java】使用 validation 完成自定义校验注解
    总括:validation让我们简化了开发过程,可以使用简单的一个注解就实现了很多常见的检验数据的功能,同时支持自定义注解。spring-boot-starter-validation是由SpringBoot整合的一套用于处理 validation的约定化自动配置启动器。Spring系列框架通过简单的安装依赖即可直接使用......
  • 由JAVA环境变量Classpath与logging.config配置冲突的异常:
     Classpath与logging.config配置冲突异常信息:     ......
  • 到底什么是Java AIO?为什么Netty会移除AOI?一文搞懂AIO的本质!
    本文由得物技术团队Uni分享,即时通讯网收录时有内容修订和大量排版优化。1、引言关于Java网络编程中的同步IO和异步IO的区别及原理的文章非常的多,具体来说主要还是在讨论JavaBIO和JavaNIO这两者,而关于JavaAIO的文章就少之又少了(即使用也只是介绍了一下概念和代码示例)。在深......
  • 10个具体项目生动精彩讲述JavaScript;超级Web应用,构建不再困难
     “JavaScript,就是那种小时候长得很丑,长大了却谁都想要的孩子。”诞生初期,由于很多所谓的“资深”程序员的滥用,让这个孩子饱受质疑,直到前几年DOM技术开始崛起,JavaScript才逐渐恢复了曾经的兴盛。并且,这时的JavaScript更多了一份成熟,少了一缕稚气。JavaScript虽然已经被当......
  • 活学活用流行的JavaScript库——《JavaScript实战》
    媒体评论“本书并不像一本教材,畅读之后,你会觉得它就是一位讲课生动的老师,带领你遨游JavaScript海洋,把你推向技术风浪的前沿,同时又给了你一个功能完备的冲浪板,接下来就是你在风口浪尖上享受JavaScript高潮的时候了。”                  ......
  • linux gpio dev,linux gpio子系统 devicetree中GPIO_ACTIVE_LOW
    一直没怎么理解GPIO_ACTIVE_LOW的作用对于以上的dts你应该再熟悉不过,当然这里不是教你如何使用dts,而是关注gpio和irq最后一个数字可以如何利用。例如rst-gpio的OF_GPIO_ACTIVE_LOW代表什么意思呢?可以理解为低有效。什么意思呢?举个例子,正常情况下,我们需要一个gpio口控制灯,我们认......