java性能测试原则_第1页
java性能测试原则_第2页
java性能测试原则_第3页
java性能测试原则_第4页
java性能测试原则_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、引言计算机软件作为人类智慧的结晶,帮助我们在这个日新月异的社会中完成了大量工作。 我们的日常生活中已经离不开软件,玲琅满目的软件已经渗透到了我们生活的各个角落,令 我们目不暇接。我们都希望软件变得更好,运行处理的速度更快,在当今硬件性能突飞猛进 的变革中,软件性能的提升也是一个永不落伍的话题。软件性能测试的实质,是从哲学的角 度看问题,找出其内在联系,因果关系,形式内容关系,重叠关系等等。假如这些关系我们 在分析过程中理清了,那么性能测试问题就会变得迎刃而解。在软件开发过程中,性能测试往往在开发前期容易被忽略。直到有一天问题暴露后,开 发人员被迫的直面这个问题,大多数情况下,这是令开发人员感觉

2、到非常痛苦事情。所以在 软件开发前期以及开发过程中性能测试的考量是必要的,那么具备相应理论知识和实践方法 也是一个优秀工程师所应当具备的素养,这里我们概括有四项原则,这些原则可以帮助开发 人员丰富、充实测试理论,系统的开展性能测试工作,从而获得更有价值的结果。实际项目中的性能测试才有意义第一个原则就是性能测试只有在实际项目中实施才是有意义的,这样才使得测试工作具 有针对性,而且目标会更加明确。这个原则中有三个类别的基准可以指导开发人员度量性能 测试的结果,但是每一种方法都有它的优点和劣势,我们将结合实际例子,来总结阐述。微观基准,可以理解为在某一个方法或某一个组件中进行的单元性能测试。比如检测

3、一 个线程同步和一个非线程同步的方法运行时所需要的时间。或者对比创建一个单独线程和使 用一个线程池的性能开销。或者对比执行一个算法中的某一个迭代过程所需要的时间。当我 们遇到这些情况时,我们常常会选择做一个方法层面的性能测试。这些情况的性能测试,都 可以尝试使用微观基准的方法进行性能测试。微观基准看似编写起来简单快捷,但是编写能 够准确反映性能问题的代码并非一件易事。接下来通过例子让我们从代码中发现一些问题。 这是一个单线程的程序片段,通过计算50次循环迭代来检测执行方法所耗费的时间体现 性能差异:public void doTest() double l;long then = System

4、.currentTimeMillis();intnLoops = 50;for (int i = 0; i nLoops; i+) l = compute(50);long now = System.currentTimeMillis();System.out.println(Elapsed time: + (now - then);private double compute(int n)if (n 0);if (n = 0) return 0d; if (n = 1)return 1d;double d = compute(n - 2) + compute(n - 1);if (Doubl

5、e.isInfinite(d)throw new ArithmeticException(Overflow);return d;执行这段代码我们会发现一个问题,那就是执行时间只有短短的几秒。难道果真是程序性 能很高?答案并非如此,其实在整个执行过程中compute计算方法并没有调用而是被编译 器自动忽略了。那么解决这个问题的办法是将double类型的“换成volatile实例变量。这 样能够确保每一个计算后所得到的结果是可以被记录下来,用volatile修饰的变量,线程 在每次使用变量的时候,都会读取变量修改后的最后的值。要特别值得注意的是,当考虑为多线程写一个微基准性能测试用例时,假如几个线

6、程同 时执行一小段业务逻辑代码,这可能会引发潜在的线程同步所带来的性能开销和瓶颈。此时 微观微基准测试的结果往往引导开发人员为了保持同步进行不断的优化,这样会浪费很多时 间,对于解决更紧迫的性能问题,这样做就显得得不偿失。我们再试想这样一个例子,微基准测试两个线程调用同步方法的情况,因为基准代码很 小,那么测试用例大部分时间将消耗在同步过程中。即使微基准测试在整体的同步过程中只 占50%,那么两个线程尝试执行同步方法的几率也是相当高的。基准运行将会非常缓慢, 添加额外的线程会造成更大的性能问题。基于微观基准的测试过程中,是不能含有额外的对性能产生影响的操作,我们知道执行 compute(100

7、0)和compute(1)在性能上是有很大差异的,假如我们的目标是对比两个不 同实现方法之间的性能差异,那么就应当考虑一系列的输入测试值作为前提,传递给测试目 标,参数就需要多样化。这里以我们的经验解决的办法就是使用随机值:for (int i = 0; i nLoops; i+) l = compute(random.nextInt();现在,产生随机数的时间也包含在了整个循环执行过程中,因此测试结果中包含了随机 数生成所需要的时间,这并不能客观的体现compute方法真实的性能。所以在构建微观基 准时,输入的测试值必须是预先准备好的,且不会对性能测试产生额外的影响。正确的做法 如下:pub

8、lic void doTest() double l;intnLoops = 10;Random random = new Random();int input = new intnLoops;for (int i = 0; i nLoops; i+) inputi = random.nextInt();long then = System.currentTimeMillis();for (int i = 0; i nLoops; i+) try l = compute(inputi); catch (IllegalArgumentExceptioniae) long now = System

9、.currentTimeMillis();System.out.println(Elapsed time: + (now - then);微观基准中输入的测试值必须是符合业务逻辑的。所有的输入的值并不一定会被代码用到, 实际的业务可能对输入的数据有特定的要求,不合理的输入值可能导致代码在执行过程中就 抛出异常而中断,从而使得我们难以判断代码执行的效率。所以在准备测试数据的时候应当 考虑到输入数据的有效性,保证代码执行的完整性。比如下面的例子输入的参数如果是大于 1476,执行会立即中断,从而影响了真实性能结果的产生。public double ImplSlow(int n) if (n 0);

10、if (n 1476) throw new ArithmeticException(Must be 1476);return verySlowImpl(n);通常情况下,对参与到实际业务计算的值提前检测对提升性能是有帮助的,但是假如用户大 多数输入的值是合理的,那么提前检查数据的有效性就显得冗余了。所以编写核心逻辑代码 的时候,我们建议只针对一般情况做处理,保证执行的效率的高效性。假设访问一个 collection对象时,每一次能够节省几毫秒的话,那么在多次的访问情况下就会对性能的提 升产生重大的意义。public class Test1 private volatile double l;p

11、rivate intnLoops;private int input;private Test1(int n) nLoops = n;input = new intnLoops;Random random = new Random();for (int i = 0; i nLoops; i+) inputi = random.nextInt(50);public void doTest(booleanisWarmup) long then = System.currentTimeMillis();for (int i = 0; i nLoops; i+) try l = compute(inp

12、uti); catch (IllegalArgumentExceptioniae) if (!isWarmup) long now = System.currentTimeMillis();System.out.println(Elapsed time: + (now - then);private double compute(int n) if (n 0);if (n = 0)return 0d;if (n = 1)return 1d;double d = compute(n - 2) + compute(n - 1);if (Double.isInfinite(d)throw new A

13、rithmeticException(Overflow);return d;public static void main(String args) / TODO Auto-generated method stubTest1 test1 = new Test1(Integer.parseInt(10”););test1.doTest(true);test1.doTest(false);总得说来,微观基准作用是有限的,在频繁调用的方法中使用微观基准的度量方法会帮助 我们检测代码的性能,如果用在不会被频繁调用的方法中是不合适的,应当考虑其它方法。宏观基准,当我们测量应用程序性能时,应当纵览整个系

14、统,影响应用程序性能的原因可能 是多方面的,不能片面的认为性能瓶颈只会在程序本身上。通过下面这个例子我们将探讨离 开宏观基准的性能测试是不可能找到影响应用程序性能真正的瓶颈。上图数据来自客户实体,触发应用程序的核心业务计算方法,该方法从数据库加载数据,LDAP查陆 (2响应客户清求(500 RPS并传导给核心业务中的计算方法,得到结果保存到数据库,最终响应客户的请求。每个图形 中的数字分别代表了这个模块所能处理客户请求的数量。核心业务模块的优化多数情况是受 限于业务的要求。假设我们优化这些核心模块,使其可以处理200 RPS时,我们发现加载数据的模块依然只能处理100 RPS,也就是说整个系统

15、的吞吐能力其实仍然为100 RPS, 最终对应用程序整体的性能提升是没有任何帮助的。从这个例子我们得知,我们花费再多的 精力在核心业务上的优化意义并不大,我们应当从整体运行情况来看,发现真正影响性能的 瓶颈来解决问题,这就是宏观基准原则的意义。折衷基准,相比微观基准和宏观基准,一个单独功能模块的性能测试,或者一系列特定操作 的性能测试被称为折衷基准。它是介于微观基准和宏观基准之间的折衷方案。基于微观基准 测试的正确性是较难把握的,性能瓶颈的判断绝不能仅仅依赖于此。如果我们要使用微观基 准作为性能的测量方法,那么不妨在此之前先尝试基于宏观基准的测试。它可以帮助我们了 解系统以及代码是如何工作的,

16、从而形成一个系统整体逻辑结构图。接下来可以考虑基于折 衷基准的测试,来真正发现潜在的性能瓶颈。需要明确的是折衷基准的测试方法并不是完整 应用程序测试的替代方法,更多情况下我们认为它更适用于一个功能模块的自动测试。批量,吞吐量和响应时间的测量方法性能测试中的第二个重要的原则是引入多样的测量方法来分析程序的性能。批量执行所用时间的测量方法(耗时法),这是种简单而快速有效的方法,通过测量完 成特定任务所消耗的时间来测量整体性能。但是需要特别注意,假如所测试的应用程序中使 用缓存数据技术来为了获得更好的性能表现时,多次循环使用该方法可能无法完全反应性能 问题。那么可以尝试在初始状态开始时应用耗时法做一

17、次性能的评估,然后当缓存建立后, 再次尝试此方法。吞吐量的测量方法,在一段时间内考察完成任务的数量的能力,被称为吞吐量测量方法。 在测试客户服务器的应用程序时,吞吐量的测量意味着客户端发送请求到服务器是没有任何 延迟的,当客户端接收到响应后,应当立即发出新的请求,直到最终结束,统计客户端完成 任务的总数。这种相对理想的测试方法通常称之为“Zero-think-time”。可是通常情况下,客 户端可能会有多个线程做同一件事情,吞吐量则意味着每秒钟内所有客户端的操作数,而不 是测量的某一个时段内的所有操作总数。这种测量经常称为每秒事务/(TPS),每秒请求 (RPS),或每秒操作数(OPS)。测试

18、所有基于客户端和服务器端应用程序都存在一种风险,客户端不能以足够快的速度发送 数据到服务器端,这种情况的发生可能是由于客户端此时没有足够的CPU资源去运行需 要数量的线程,或者客户端必须耗用更长的时间来处理当前的请求。这种情况下,实际上测 量的是客户端的性能,而非服务器的性能,与吞吐量测量方法是背道而驰的。其实这种风险 是由每个客户端线程处理任务的数量和硬件配置决定的。“Zero-think-time”在吞吐量测试中 可能经常会遇见以上的情况,由于每个客户端线程都需要处理大量的任务,因此吞吐量测试 通常被应用于较少的客户端线程程序。吞吐量测量方法也同样适应用于带有缓存技术的应用 程序,尤其是当

19、测试的数据是一个并不固定的情况下。响应时间的测量方法,响应时间的测量方法是指客户端发出一个请求后直到接收到服务 器的响应返回后的时间消耗。响应时间测量方法不同于吞吐量测量方法,在响应时间测试过 程中,客户端线程可能会在操作的过程中某一时刻休眠,这就引出“think- time ”这个关键词, 当 “think- time ”被引入到测试过程中,也就是意味着待处理任务量是固定的,测量的是服务 器响应请求的速率是怎样的。大多数情况下,响应时间的测量方法用来模拟用户真实操作, 从而测量应用程序的性能。多变性性能测试的第三个原则是理解测试结果如何随时间改变,即使每一次测试使用同样的数 据,可能获得的结

20、果也是不同的。一些客观因素,比如后台运行的进程,网络的负载情况, 这些都可能带来测试结果的不同,所以在测试过程中存在着一些随机性的因素。这就产生了 一个问题:当比较两次运行得到的测试结果时,它们之间的差异是由回归测试产生的,还是 是随机变化而导致的呢?我们不能简单的通过测量多次运行回归测试的平均结果来评判性能的差异。这时我们可 以使用统计分析的方法,假设两种情况的平均值是一样的,然后通过概率来判断这样的假设 是成立的。如果假设不成立,那么就说明有很高的概率证明平均数存在差异。在回归测试中原始代码被视为基线,新增加的代码称为样本。三次运行基线和样本,产 生时间如表1:次教菽*博本 TOC o 1

21、-5 h z 100.5g1 151.205,.箸软件测试的自我修养平均1 0.75看起来样本的平均值显示有25%的提升,可事实证明样本和基线有相同性能的概率是43%。 也就是说57%的概率存在性能上的不同。43%是基于T检验所得到的结果,T检验主要 用于样本含量较小(例如n30),总体标准差a未知的正态分布资料。t检验是用t分布 理论来推论差异发生的概率,从而比较两个平均数的差异是否显著。它与z检验、卡方检 验并列。现在的T检验结果告诉我们这样一个信息::57%概率显示样本和基线存在性能差 异,差异最大值是25%。也可以理解为性能差有57%的置信度向理想发现发展,结果有25% 的改善。在考量回归测试的结果时,离开了统计分析的方法,而只关注平均值来做出判断,含糊 的理解这些数

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论