性能测试的目标
性能测试不同于功能测试,不是对与错的检验,而是快与慢的衡量。在进行真正的性能测试之前要先搞清楚目标:
1. 在确定的硬件条件下,可以支持的并发数越大越好,响应时间越快越好。具体需要达到的并发数是多大,要求的响应时间是多快,由产品经理来提出。
2. 在确定的硬件条件下,测试得到最大并发数和相应的响应时间之后。如果增加硬件投入,可以得到怎样的性能提升回报? (系统扩展性和伸缩性测试,Scalability)
这里的硬件条件包括:cpu,memery,I/O,network bandwidth。
性能测试中的基准测试 Benchmarking
与功能测试相似,性能测试也要设计测试用例,不同的是在正式开始你的业务测试用例之前你要先进行一下基准测试。为什么呢?其实就是先要量一下你的硬件的能力,不然,如果你的测试结果不好,你怎么知道是硬件慢还是你的软件的问题。这些硬件测试包括:
1. 网络带宽测试, 你可以通过copy大文件的方式测试你的网络的最大带宽是多少。
2. cpu,你可以利用比较复杂的算法来衡量cpu的快慢
3. memery,这个不用测试,你知道memery的大小
4. IO, 也可以通过copy大文件来测试
这些基准测试用例在后面的调优过程中,还可以用来衡量你修改之后真的变好了吗。
设计你的业务测试用例
比较理想的测试用例就是要尽可能模仿真实世界的情况,这往往做不到,尤其是对于新产品来说。你可以先录制一些用户最常用,最典型的case作为起点。
另外,对于并发的概念需要搞清楚。并发用户,通常是指同时在线的用户,这些用户可以能在用你的系统的不同的功能,注意并不是说大家都在做同一件事情。对某一个事务并发请求是指某一个request的并发调用。
对于后一种并发,你往往需要计算在用户量最大的时候,大概大家都集中的在干哪一件事情,这个请求一定要够快才好。
设计好这两种测试用例以后,在后面的调优过程中,他们就成了衡量你的改进的成效的衡量的标尺。
性能调优
性能调优要从底层开始,基本上要从OS开始,到JVM,Cache,Buffer Pool, SQL,DB Schema, 算法。
一次不要改的太多,改一点,测一下,这可是个慢功夫,需要有耐心。
在执行测试的时候还要注意,要遵循相同的过程,系统需要在重启之后先热身再开始真正的测试,不然你会发现你的测试结果很不一样,琢磨不定。
还有,要注意你的客户端的能力,比如JMeter,很需要内存,别因为客户端不行,误以为是你的系统的问题,那就太乌龙了。
在测试调优的时候,需要借助一些监控工具比如JConsole,来监控系统的状况,找到系统的瓶颈,所谓瓶颈,就是最慢的那个部分,也常表现为100%被占满。比如你的内存或者cpu被用尽了。如果cpu和内存还没有用尽,说明他们在等某个资源。这时候需要用profile工具去寻找,比如JProfile,YourKit。
利用性能监控日志
因为性能的问题不是很容易重现,当product环境中遇到性能问题的时候,如果是数据的问题,也许当你把product 数据copy到你的测试环境中,就能重现比较慢点查询,加以改进。但是如果是并发用户或者网络等运行时环境的问题,你就很难重现。这时,如果你能通过日志看到那些关键的响应慢的方法,也许可以帮助你快点找到问题所在。下面的代码可以帮你做到这一点,仅供参考:
- import org.slf4j.Logger;
- public class TraceUtil {
- final Logger logger;
- final long threshold = 1000;
- private long begin;
- private long offtime = 0;
- private String threadInfo;
- private String targetId;
- public TraceUtil(Logger logger, Thread thread, String targetId, long begin) {
- this.logger = logger;
- this.threadInfo = thread.getId() + "-" + thread.toString();
- this.targetId = targetId;
- this.begin = begin;
- }
- public void trace(String targetEvent) {
- long duration = System.currentTimeMillis() - begin;
- long increment = duration - offtime;
- offtime = duration;
- float percentage = (float) increment / (float) duration * 100;
- if (duration > threshold && percentage > 20) {
- logger.error(
- "Response time is too large: [{}], {}/{} ({}), {}, {}",
- new String[] { threadInfo + "", increment + "",
- duration + "", percentage + "%", targetEvent,
- targetId });
- }
- }
- }
利用JVM的MXBean找到blocked的点
当你发现JVM占用的cpu很高,而且响应时间比较慢,很可能是被IO或者网络等慢速设备拖住了。也有可能是你的方法中某个同步点(同步方法或者对象)成为性能的瓶颈。这时候你可以利用JVM提供的monitor API来监控:
- <%@ page import="java.lang.management.*, java.util.*" %>
- <%!
- Map cpuTimes = new HashMap();
- Map cpuTimeFetch = new HashMap();
- %>
- <%
- out.println("Threads Monitoring");
- long cpus = Runtime.getRuntime().availableProcessors();
- ThreadMXBean threads = ManagementFactory.getThreadMXBean();
- threads.setThreadContentionMonitoringEnabled(true);
- long now = System.currentTimeMillis();
- ThreadInfo[] t = threads.dumpAllThreads(false, false);
- for (int i = 0; i < t.length; i++) {
- long id = t[i].getThreadId();
- Long idObj = new Long(id);
- long current = 0;
- if (cpuTimes.get(idObj) != null) {
- long prev = ((Long) cpuTimes.get(idObj)).longValue();
- current = threads.getThreadCpuTime(t[i].getThreadId());
- long catchTime = ((Long) cpuTimeFetch.get(idObj)).longValue();
- double percent = (double)(current - prev) / (double)((now - catchTime) * cpus * 1000);
- if (percent > 0 && prev > 0) {
- out.println("<li>" + t[i].getThreadName()+"#"+t[i].getThreadId() + " Time: " + percent + " (" + prev + ", " + current + ") ");
- String locked = t[i].getLockInfo()==null?"":t[i].getLockInfo().getClassName();
- out.println(" Blocked: (" + t[i].getBlockedTime() + ", " + t[i].getBlockedCount() + ", " + locked + ")</li>");
- }
- }
- cpuTimes.put(idObj, new Long(current));
- cpuTimeFetch.put(idObj, new Long(now));
- }
- %>
同步是性能的一大瓶颈
通过监控发现,大量线程block在一个同步方法上,这样cpu也使不上劲。当你发现性能上不去,IO和网络等慢速设备也不是问题的时候,你就得检查一下是否在某个关键点上使用了同步(synchronizae)。有时候也许是你应用的第三方的jar里面的某个方法是同步的,这种情况下,你就很难找到问题所在。只能在编写代码的时候看一下你引用的方法是否是同步的。
相关推荐
下面将详细介绍Java EE性能调优的相关知识点。 1. **JVM参数调优**: - **内存配置**:调整初始堆大小(`-Xms`)和最大堆大小(`-Xmx`),以适应应用的内存需求,防止频繁的垃圾收集。 - **垃圾收集器选择**:...
4. **JAVA应用性能测试调优经验总结** - **GC调优参数的使用**:调整垃圾收集器参数,如-XX:MaxTenuringThreshold控制对象晋升老年代的阈值,-XX:GCTimeRatio设置垃圾收集时间占总运行时间的比例,可以减少停顿时间...
【Java EE性能优化】 Java EE(Java Platform, Enterprise Edition)是用于构建企业级Web应用的标准框架,其性能直接影响到整个系统的效率和响应速度。在实际应用中,开发者经常会遇到性能瓶颈,以下是一些常见的...
WebLogic Server是Oracle公司的一款企业级应用服务器,广泛应用于Java EE应用的部署与管理。性能调优对于确保WebLogic Server上运行的应用程序能够高效、稳定地运行至关重要。性能调优主要涉及对应用程序、服务器和...
【JAVA EE 开发测试文档】是一系列关于Java企业级应用开发和测试的综合资源集合,包含多本PDF手册,由于文件大小限制,被拆分成多个部分进行上传。这些手册覆盖了从入门到高级的多个主题,旨在帮助开发者和测试...
作者可能会详细解释如何设置和运行Java EE应用,以及如何利用诸如JProfiler、VisualVM等工具进行性能分析和调优。 书中的第二版可能着重介绍了自第一版以来Java EE的重大更新,例如从Java EE 7到Java EE 8,甚至是 ...
**标题与描述:**《Apress.Begining EJB3 Java EE 7 Edition.2013》是一本面向初学者介绍如何使用EJB3构建Java EE 7企业级应用程序的指南。 **标签:**EJB3、Java EE 7 #### 二、核心章节内容概览 本书由多个章节...
5. **Java SE与Java EE应用的调优**:针对不同的应用类型采取不同的调优策略是提高性能的关键。 6. **微基准测试**:正确地进行微基准测试有助于避免误导性的结论,确保编写出高性能的应用程序。 7. **实践中的案例...
在部署和调优后,需要进行详尽的性能测试,如压力测试、负载测试和稳定性测试,以验证系统的性能表现和稳定性。这通常包括模拟大量并发用户、长时间运行测试以及监控关键性能指标(如CPU使用率、内存消耗、响应时间...
同时,日志分析和性能测试工具如JMeter、VisualVM也是必不可少的。 7. **网络优化**:网络延迟和带宽限制可能成为性能瓶颈。检查网络配置,优化网络传输,如启用HTTP压缩、减少不必要的网络通信等,有助于提升整体...
- **A:** 确保应用符合Java EE 7规范,并在多个环境中进行充分测试。 #### 八、总结 《Java EE 7 Developer Handbook》是一本全面介绍Java EE 7平台的参考书,涵盖了从基础概念到高级主题的所有方面。无论是初学者...
4. **Java开发**:包括编写、调试Java代码,使用内置的代码提示和重构工具,以及如何进行单元测试和性能测试。 5. **Web应用开发**:涵盖HTML、CSS、JavaScript的编辑与调试,JSP、Servlet的开发,以及如何部署和...
《MyEclipse 6 Java EE 开发中文手册》是一份专为Java EE开发人员准备的详尽指南,它涵盖了MyEclipse 6版本中的各项功能和特性,旨在帮助用户高效地进行企业级应用的开发。这份手册以中文呈现,使得国内开发者能够无...
结合像 DayTrader 这样的基准测试,可以帮助识别应用程序中的热点并针对性地进行调优,以实现最佳性能。然而,每个应用程序都有其独特性,因此,任何调优建议都需要在实际环境中进行验证和调整。