java 测试java代码性能测试工具 指的是什么呀

软件测试的发展前途是做什么?和写java有什么区别_百度知道
软件测试的发展前途是做什么?和写java有什么区别
安全测试11.转为需求人员5;1.转为老板的纵观测试行业基本知识包括以下几方面1.测试管理工具
QC 禅道 jira
bugziller6.也见过转为软件开发的 8.发展成为资深测试工程师(要掌握的知识很多)2.如果可以去写java吧.转为技术支持7.转为产品人员4.性能测试
自动化测试
两个基本方向8.管理能力 9.行业知识 10.转为销售6.测试基础2.linux3.测试工具
loadrunner
juntil7.发展成为测试经理3.数据库
51。(指大部分)目前主要发展方向有一下几点。属于开发(一般开发相对于软件测试来说工资要高一些)2.目前测试并没有太好的发展.脚本 ruby
perl其中的一种或2种4
其他类似问题
为您推荐:
软件测试的相关知识
其他1条回答
级的测试工资都很低的.sina,有两条路线可走.html" target="_blank">http://blog,以后转行为管理.com,相对要求也低一些://blog。<a href="/s/blog_620fcez。二是走管理路线:一是走技术路线。要想工资高就必须向上发展.cn/s/,以后可转行为开发.sina
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁课程名称读取中
支付宝支付
由百度提供技术支持
&学院APP&&
扫描微信二维码精彩活动、课程更新抢先知
下载客户端,离线视频任您学
1.&1-课程介绍与项目介绍
2.&2-测试环境搭建和被测程序部署
3.&3-性能测试需求分析
4.&4-性能测试用例设计
5.&5-脚本开发-1
6.&6-脚本开发之另类参数化技巧
7.&7-性能测试场景设计
8.&8-性能测试场景监控实战
9.&9-性能测试场景执行
10.&10-性能测试结果分析
加入购物车
【课程类型】实战教学
【难度级别】高级
【适合人群】所有人
【课程介绍】 适用人群:适合有基础的人,无基础的建议先观看疯狂LoadRunner性能测试实战视频以及测试环境搭建实战视频;友情提示,觉得自己是高手的请绕行!
课程特点:以真实OA系统为例讲解高级性能测试流程以及重要知识点!(包括但不限于下方内容)
1、项目介绍与部署
2、真实性能需求如何提取
3、高级用例编写
4、脚本开发与调试(非常规的)
5、场景建模与监控实战
6、性能测试结果分析
【课程目标】 完整展示JAVA项目的性能测试过程,使得学员掌握如何进行项目测试,包括但不限于如何挖掘需求、分析性能指标、设计场景、编写脚本、监控部署、分析结果等。QQ群
【课程计划】 10节
全部评价(0)
17课程148782学员
参考知识库
为您推荐课程
讲师:赵强 3课时
讲师:赵强 15课时
讲师:赵强 1课时
讲师:赵强 0课时
讲师:赵强 10课时本文由&– 小峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的!
作为测试驱动设计和开发的忠实粉丝,我相信创造良好的测试是我们作为Java开发人员可以做的最重要的事情之一。我们写测试出于许多原因:
塑造系统的设计。我们知道输入和输出应该是什么样的,但是我们需要创建什么对象来做到这一点呢?代码应该塑造成什么样的“形状”?编写测试可以让我们知道应该创建什么样的代码。
为了确保初始和持续的正确性。让我们的应用程序如期望地那样运作并且始终如一地精确很重要。测试应该竭力确保做到这一点。
文档。测试是系统的文档,因为它会说明它应该做什么以及应该怎么做。
那么“好的测试”到底是什么样子的呢?
给测试命名
测试的名字至关重要,特别是从文档角度来看的话。我们应该能够大声读出测试的名字就像一组需求一样。事实上,有一个伟大的IntelliJ插件,叫Enso,它会将你的测试名转变为恰好位于每个类旁边的语句,这样你就可以明明白白地看到你在做什么。
不要以“test”开始命名测试的名称。这是来自于JUnit初期的后遗症,当需要它执行的时候。你的Test类将在Test文件夹中,在一个最后有Test这个单词的类中。会有一个@Test的注解。我们知道这是一个测试。
你也应该避免以“should”或“will”开头。这些都是干扰词。既然你已经为这个功能写了一个测试,那我们就知道它“should或will”工作(如果不能工作的话,那我们知道我们需要修复它)。
将测试名称当作一个要求。 下面是一些例子
addingNumbersWillSumValuesTogether()
explodesOnNegativeID()
notifiesListenersOnUpdates()
不要害怕表达出来。如果你的测试名称确实需要很长的一串单词,那就这么做,只要它能清楚说明将发生什么事情。
测试将分为3个部分:设置,操作,断言。
对你的测试设置代码应该只与在测试中被断言的值相关。如果你有多余的设置代码,那就会搞不清楚它是什么,并且与测试不相关。
这可以通过多种方式实现:
将通用设置移动到使用@Before注解的具体设置方法。
将重复的设置代码移动到辅助方法
使用Maker来创建复杂的测试对象,并只设置测试中相关的值。
我重申一下:每个测试的设置部分应该只有与最后被断言的值相关的代码。
不好的例子:
public void returnsBooksWherePartialTitleMatchesInAnyCast(){
Bookstore bookstore = new Bookstore();
Book harryPotterOne = new Book("Harry Potter and The Philosopher Stone");
bookstore.add(harryPotterOne);
bookstore.add(new Book("Guardians of the Galaxy"));
Book harryPotterTwo = new Book("The Truth about HARRY POTTER");
bookstore.add(harryPotterTwo);
List&Book& results = bookstore.findByTitle("RY pot");
assertThat(results.size(), is(2));
assertThat(results, containsInAnyOrder(harryPotterOne, harryPotterTwo));
书店的初始化发生在测试中,书本的创建也是。这让测试显得混乱不堪,让人搞不清楚发生了什么事情。
好的例子:
private Bookstore bookstore = new Bookstore();
private Book aHarryPotterBook = new Book("Harry Potter and The Philosopher Stone");
private Book anotherHarryPotterBook = new Book("The Truth about HARRY POTTER");
private Book aBook = new Book("Guardians of the Galaxy");
public void returnsBooksWherePartialTitleMatchesInAnyCast(){
bookstore.add(aHarryPotterBook);
bookstore.add(aBook);
bookstore.add(anotherHarryPotterBook);
List&Book& results = bookstore.findByTitle("RY pot");
assertThat(results.size(), is(2));
assertThat(results, containsInAnyOrder(aHarryPotterBook, anotherHarryPotterBook));
初始化发生在字段中,这样在测试中发生了什么一清二楚。
小菜一碟!最好保持到一行,你要进行测试的独立操作。有时候,你专门测试的是输出是什么,如果某些东西被多次调用,或者在某些优先操作之后调用的结果是什么,所以这不是一个硬性规定。当读取测试时,用户应该快速而轻松地能说“将这些值设置成这样,如果我执行这个操作/这些操作,那么这是预期的结果”。在上面的例子中,便是bookstore.findByTitle()方法。
使用Hamcrest。 Hamcrest是一个很棒的库,给我们一个流畅的API用来写入测试。不会像这样的代码:
assertEquals(results.size(), 2);
assertTrue(results.contains(aHarryPotterBook))
assertTrue(results.contains(anotherHarryPotterBook))
我们可以一目了然、轻松地阅读像这样的代码:
assertThat(results.size(), is(2));
assertThat(results, containsInAnyOrder(aHarryPotterBook, anotherHarryPotterBook));
这些相当简单的例子:Hamcrest有很多伟大的方法,使编写复杂测试变得很容易,并允许你创建自己的匹配器。
当然,理想情况下,我们希望有一个独立的断言。这可以让我们知道我们正在测试什么,并说明我们的代码没有意外情况。就像这篇文章中所说的那样,这不是一个硬性的规则,因为在某些情况下,这是必要的,但如果你有这样一个的测试:
assertThat(orderBook.bids.size(), is(4));
assertThat(orderBook.asks.size(), is(3));
assertThat(orderBook.bids.get(0).price, is(5200));
assertThat(orderBook.asks.get(2).price, is());
assertThat(orderBook.asks.get(2).isBuy, is(false));
那么要理解测试哪里失败或哪条断言重要就变得困难多了。
你也可以在Hamcrest中编写自定义的匹配器,因为Hamcrest可为复杂断言提供一个优雅的解决方案。如果你需要在一个循环中运行断言,或者你有大量的字段要断言,那么一个自定义的匹配器可能才是上上之选。
一个测试的最重要的部分之一是,当它失败时,哪怕是一个5岁孩子也应该看得出什么地方出了错以及哪里错了。失败的消息一定不能含糊。关于这方面的解决方法是:
如果做任何类型的对象比较,那么保证对象有一个体面的toString()消息。没有什么比&MyObject @ 142131&不匹配更糟的了。
想要做的更好的话,可以对你的对象使用自定义匹配器。你可以准确地知道哪些字段未能匹配。
确保明确为什么你要选择和这个值作比较。例如,如果你正在将一个字段值与数字3000比较,那么为什么是3000?你应该费力地明白这一点。显然,这个数字不是随便得来的,并且还要确保该变量的命名可以显示它的值是如何得来的。
所有这些都应该是在一个适度的常识范围内。没有严格规定!
你还有什么要补充的吗?欢迎告诉我们。
译文链接:
英文原文:
翻译作者:&– 小峰
[&转载必须在正文中标注并保留原文链接、译文链接和译者等信息。]
在文章中找不到问题答案?您还可以
热门栏目订阅Java性能优化指南系列(一):概述和性能测试方法 - 博客频道 - CSDN.NET
测试鸟的博客
一个吸纳互联网架构相关思想和技术的驿站
分类:编程语言
源文章:http://blog.csdn.net/qq_/article/details/
[编程语言-Java](转载)
Java性能分析是一门艺术和科学;科学指的是性能分析一般都包括大量的数字、测量和分析。绝大多数的性能工程师都有科学背景,运用科学的严谨是获取最大性能的重要组成部分。艺术部分指的是什么呢?性能调优是部分科学部分艺术的观点是很早就有的,但是关于性能的主题很少会给定特定的知识,这就是艺术的部分了,它和我们平常接受到的培训是不一样的,培训是确定了的。还有部分原因是对于某些人来说,性能调优是建立在深入的知识和经验上面的。这里艺术就是知识、经验和直觉的使用。这本书不能帮助我们提升经验和直觉,但是可以帮助我们提升对知识的深入理解,我们持有这样的观点:多次运用知识能够提升我们称为Java性能工程师的能力。这本书的目标就是给予我们对Java平台性能方面的深入理解。这种知识主要分为两大部分:一是JVM本身的性能,研究JVM的配置是如何影响程序的各方面性能的。其它语言的有经验的开发人员会发现这个调优是比较繁琐的,尽管实时上JVM的调优和C&#43;&#43;程序员在编译的时候测试和选择不同编译器参数或者是PHP程序员在php.ini文件设置合适的变量是一样的。二是理解Java平台的特性是如何影响性能的。注意这里的平台,一些特性(比如:线程和同步)是语言的一部分,另外一些特性(比如:XML解析性能)是Java的标准API。尽管Java语言和Java
API是不同的,但是这里我们把他们看成是类&#20284;的。JVM的性能很大程度上是和调优参数相关的,平台的性能则和应用代码的优劣相关。很多时候,代码开发人员和性能测试小组是分割开的,认为他们是不同方面的专家。只有性能工程师能够对JVM虚拟机进行调优,以榨取更多的性能;只有开发人员才会关心代码写的好不好。区分这个是没有什么作用的--任何在Java平台上工作的人都需要了解这些。
平台和约定
本书使用的平台是:Java&7update&40和Java&8;Java7是进行性能调优的一个好的起点,因为它提供了很多新的特性,比如:G1垃圾回收器,同时还提供了一些和性能相关的工具,便于我们可视化的查看Java应用的工作细节。Java8也做了较大幅度的改进(比如:引入lambda表达式)。尽管所有平台都会做兼容性测试,以便实现Java规范的功能;但对于本书来说,这里的兼容性是不够的,特别是tuning
flag,每个JVM都会实现一个或多个垃圾收集器,但是它们的调优参数一般是不一样的,尽管这本书讨论的很多概念是适用于所有Java的实现平台的,但是对于一些调优参数和建议,那只适用于Oracle的JVM(HotSpot)。
除了少部分例外,JVM会接受两种参数:boolean参数和带有参数的参数。Boolean参数使用-XX:&#43;FlagName来开启参数,使用-XX:-FlagName来关闭参数。带有参数的参数,使用-XX:FlagName=something来设置参数&#20540;。当介绍某个参数的时候都会讨论它的默认&#20540;。这个默认&#20540;是不同方面的组合,比如:当前JVM运行在什么操作系统上面以及其它JVM命令行参数是什么。如果有疑问,可以使用-XX:&#43;PrintFlagsFinal来查看在特定平台上面,给定JVM命令行参数会给其它参数什么默认&#20540;。对于这些会根据其它参数和平台来自动选定调优参数的过程,我们叫做ergonomics(不知道怎么翻译)。Client class和Server
class:当JVM运行在32-bit的windows服务器上(不管有多少个CPU),或机器只有一个CPU,那么这台机器是Client
class。其它机器都称之为server class
写更好的算法
写更少的代码:需要编译的代码越多,代码运行快需要更多的时间;分配和丢弃的对象越多,GC需要更多的工作;分配和回收更多的对象,GC周期会更长;加载的类越多,程序启动需要更长的时间;执行的代码越多,命中硬件缓存的可能性越小;执行的代码越多,需要的时间越长。不要过早优化数据库(或其它第三方资源)常常是瓶颈:
针对一般情况进行优化:1)对代码进行分析,并关注分析中消耗时间最长的部分,这也不是说只关注分析中的方法&2)使用奥卡姆剃刀定律来诊断性能问题,最新加入的代码比系统配置更有可能引起性能问题,而系统配置比JVM或操作系统的bug更有可能引起性能瓶颈。一个测试用例很有可能会发现一个潜在的性能问题,但是我们不会立马就去优化,而要看看这个测试用例是否是经常发生的。3)使用更简单的算法来完成大多数的工作。
测试真正应用
第一个原则就是性能测试必须在即将上线的产品上进行测试。
Microbenchmarks
Microbenchmarks是为了衡量非常小的代码单元的性能而设计的测试。比如:使用Synchronized和不使用Synchronized的方法;使用线程池和不使用线程池的开销;使用算术算法和另外一种实现的时间比较等等。Microbenchmarks写的很准确是非常难的。比如:
public&voiddoTest(){
&&&&&&&&&&&&&&&&// Main Loop
&&&&&&&&&&&&&&&&double&l;
&&&&&&&&&&&&&&&&long&then=&System.currentTimeMillis();
&&&&&&&&&&&&&&&&11
&&&&&&&&&&&&&&&&for(int&i=&0;&i&&nLoops;&i&#43;&#43;)
&&&&&&&&&&&&&&&&l=fibImpl1(50);
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&long&now=&System.currentTimeMillis();
&&&&&&&&&&&&&&&&System.out.println(&Elapsedtime:
&&&#43; (now-&then));
&&&&&&&&...
&&&&&&&&privatedouble&fibImpl1(int&n)
&&&&&&&&&&&&&&&&if(n&&0)throw
new&IllegalArgumentException(&Must be & 0&);
&&&&&&&&&&&&&&&&if(n==&0)return&0d;
&&&&&&&&&&&&&&&&if(n==&1)return&1d;
&&&&&&&&&&&&&&&&double&d=&fibImpl1(n-2)
&#43;fibImpl(n-&1);
&&&&&&&&&&&&&&&&if(Double.isInfinite(d))throw
new&ArithmeticException(&Overflow&);
&&&&&&&&&&&&&&&&return&d;
&上面的程序存在几个问题,第一,因为变量'l'没有使用,所以编译器会优化掉调用fibImpl1的所有代码,所以实际执行的就是打印时间的代码,根本测试不到fibImpl1的性能。第二,因为我们的目的是得到第50个Fibonacci的&#20540;,对于比较智能的编译器,可能会去除循环。第三,必须要对正确的输入进行测试,因为在实际运行的时候,输入一般都是正确的。
注意:Java代码有一个特征就是:执行的次数越多,它执行得越快(所谓:warm-up
period)。所以在进行microbenchmark的时候需要包含warm-up
period,以便给予编译器产生优化代码的机会。
还有一点要清楚的是:额外编译效益(Complilation
effects)。编译器会使用分析回馈(profile
feedback),编译使用代码的分析回馈来决定在编译一个方法的时候使用的最佳优化手段。分析回馈(profile
feedback)是基于:方法频繁调用的程度、它们被调用时的栈深度以及它们参数的真正类型等等----一句话就是基于方法代码运行的环境。编译器对代码的优化,在microbenchmark时候比在代码运行在应用时更加频繁。如果使用同样的microbenchmark类来评测第二个Fibonacci的实现方法,那么各种编译效应(Complilation
effects)都有可能会发生,特别是两个Fibonacci实现分别在不同的类中。最后要说明的是mircrobenchmark真正意味着什么?在benchmark中,总时间(比如上面讨论的Fibonacci)可能是循环很多次得到的,一般以秒为单位;但是对于每一次循环的时间,可能是以纳秒为单位。是的,随着纳秒的增加,逐步会变成一个性能瓶颈。但是,如果被测试的函数执行的次数很少,那么在纳秒级别进行优化就没有意义了。
Macrobenchmarks
用于测量一个应用的性能的best thing(最佳东西?)就是应用本身,并结合它使用任何外部资源。如果应用调用了LDAP的API来确认用户的身份,那么测试的时候就会考虑LDAP调用。撇开LDAP进行测试对于模块测试是有意义的,但是对于性能测试,必须要考虑到LDAP调用。
随着应用的增长,满足上面说的准则(使用应用本身并结合它使用的外部资源进行测试)会变得更加重要,但是也变得更加困难。复杂系统比组成它的各个部分之和更加复杂,当把各个部分组合在一起的时候,它们的行为会变得非常不一样。比如:如果我们mock了数据库,那就意味着我们不用关注数据库的性能了。但是,在真正运行的时候,数据库连接会消耗很多heap
space来存放它们的缓存数据;网络会变得更加繁忙,因为传输数据会增加;代码的优化会变得非常不同(简单的代码和复杂的代码)。CPUpipeline和Cache在较短的代码路径上比在较长的代码路径上更高效等等。另外一些原因就是资源的分配。在理想环境下,对应用中的每一行代码都有足够的时间进行优化,但是在现实环境中,对优化消耗的时间是有要求的,并且只优化复杂环境下的一部分也许不会立马得到很好的效果。考虑下图中,用户发送数据到系统,首先确认用户权限,然后做一些业务相关的计算,然后从数据库中加载所需的数据,再做一些业务相关的计算,并把一些数据存入数据库,最后向用户发送响应。下图中的每个框都是一个小模块,框中小括号部分是该模块最大处理的并发数。
从业务的角度来看,业务相关的计算是最重要的,这也是整个系统的目的;但是在上面的例子中,将它们的处理速度提升1倍是没有意义的(因为LoadData的RPS只有100)。任何应用(包括:单机JVM)都可以模块化为上面这样的一个一个步骤,每个步骤都以一定的速率向下一个步骤传输数据。
小贴士:如果有多个JVM同时运行在同一台机器上,我们必须要将所有JVM作为整体同时进行测试;因为有可能出现这种情况,单个JVM运行得很好,但是当多个JVM同时运行的时候,一些应用的性能会非常不同,比如:一些应用在GC的时候会占用比较多的CPU,当它在独立运行的时候没有问题,但是如果有其它应用一起运行的时候,它就可能得不到充分的CPU,导致运行性能下降。这就是为什么我们要对应用进行整体测试的一个理由。
Mesobenchmarks
对于JAVA SE和JAVA
EE都有一系列称之为microbenchmark的测试;对于Java
SE工程师来说,microbenchmark意味着非常小的测试单位(比上文中的Fibonacci还要小);而Java
EE工程师,microbenchmark意味着性能测试的某个方面(仍然需要执行比较多的代码),举个例子:从应用服务器的某个JSP返回结果有多快;但是在这个过程中有非常多的操作,比如:socket管理的代码,请求处理等等,这个和Java
SE里面的microbenchmark测试是不一样的。但是这个测试也不是Macrobenchmark,因为它没有登陆,没有会话管理,没有使用Java
EE的其它特性,我们称之为Mesobenchmark。
本书中的样例都是基于下面这样一个应用程序:它用于计算一定时间范围内某只股票的历史最高和最低的价&#26684;以及在这段时间内的价&#26684;偏差。类:StockPrice用来存储给定日期的该股票的价&#26684;范围。
样例应用就是处理StockPrice的一个集合;这个集合代表这支股票一段时间的历史(1年或25年),所以有下面的接口:
这个类的基本实现就是从数据库中加载一些列的价&#26684;
注意到:curDate是按天进行增加的。
另外要注意的是这个类的性能和BigDecimal的性能是精密相关的;之所有选择这个类,有两点:1)提升计算的精度&2)对于我们做为例子来说,BigDecimal的计算量有助于增加业务的计算量下面一个函数是对BIgDemial进行平方根求解(使用巴比伦方法):
这个实现不是最高效的算法,但是这么做是故意的,它可以增加些业务计算的时间。
接口StockPriceHistory的标准方差、平均价&#26684;以及直方图实现都会产生新的&#20540;。在许多例子当中,这些&#20540;或者提前计算出来(在将数据从EntityManager中加载的时候)或者延迟进行计算(等到调用对应的函数)。同样的,接口StockPrice引用了一个StockOptionPrice接口,它用来存放该股票给定日期的可选价&#26684;。这些价&#26684;也可以提前或延迟进行计算。无论是提前计算和延迟计算,这些接口的定义可以对在不同情况下,将这两种方式进行比较。这些接口也天然的复合J2EE应用:用户通过访问一个JSP页面,输入股票的代码和起止日期。这个请求会被一个Servlet进行处理(解析参数,访问stateless
EJB),得到结果后,将响应转到一个JSP页面上,它负责将数据&#26684;式化为HTML页面。
这个类可以注入不同的history bean的实现(提前计算或延迟计算);它还可以缓存数据(或不缓存),这个对于一个企业应用是很平常的事情。
理解吞吐量、处理时间(批量操作)和响应时间
处理时间(批量操作)
测试性能的一个最简单的方式就是看看应用在多长时间内能够完成某个任务。比如:获取10000只股票的25年内的历史纪录,并计算这些价&#26684;的标准方差;生成某个公司5万名员工的工资报告;执行1百万次等等对于非Java程序,这些测试都是很显然的,写好程序,然后进行执行并评估时间。但是对于java来说,就不是这样了,因为它有JIT(Java即时编译器)。这个过程会在第4章进行介绍,简单来说就是Java代码需要几分钟(或更长)的时间来达到最优化,这个时候代码执行的性能才是最高的。因此,Java性能的研究非常关注warm-up
period,性能测试通常在代码执行了足够长的时间后才启动测试,因为这个时候的代码才是最优化的。注意:warm-up
period通常是指JIT编译和优化代码的时间,但是还存在其它因素会影响warm-up
period时间的长短的。比如:JPA通常会缓存数据;操作系统也会对文件进行缓存等等。但是另一方面,通常情况下应用的性能关注的是从启动到结束的时间,用户不会关注你的warm-upperiod的时间是多长。
吞吐量的测量是指在给定时间内,应用可以完成的工作量。一般情况下,测试吞吐量都需要一个客户端不停的发送请求给服务端,但并不是所有吞吐量测试都需要这样;对于独立程序测试吞吐量就像测试程序处理时间一样简单。吞吐量可以使用TPS、RPS或OPS来表示。所有client-server测试的运行都存在一个风险:客户端不能足够快地发送数据到服务端。吞吐量测试比响应时间测试需要更少的client线程,因为吞吐量测试基本没有什么业务逻辑吞吐量测试常常需要经过warm-up
period时间后进行,特别是当被测量的应用工作集不是固定的(不知道什么含义?)
响应时间是指请求从发送到接收到响应经历的时长。响应时间测试和吞吐量测试的区别是响应时间测试的客户端线程在操作之间会睡眠一段时间。这段时间,我们称之为:think
time。响应时间测试更加接近于模拟用户的行为。将响应时间考虑进测试当中,吞吐量就变得固定:给定数目的客户端使用给定think
time来执行请求,通常会产生同样的TPS(当然,肯定有细微的变化)。在这个时候,请求的响应时间是更重要的测量目标:服务端的效率是通过它对固定数目的负载响应有多快来衡量的。
小贴士:响应时间和吞吐量:使用包含think
time的客户端来进行吞吐量测试有两种方式。最简单的方式是让客户端在请求之间睡眠一段时间:
在这种情况下,吞吐量在一定程度上依赖于响应时间。如果响应时间是1秒,那么客户端每31秒发送一个请求,因此吞吐量为0.032OPS;如果响应时间是2秒,那么客户端每32秒发送一个请求,吞吐量变为0.031OPS。
另外一种方式是使用cycle time(而不是think
time)。Cycle time设置请求之间的总时间为30秒,因此客户端睡眠的时间依赖于响应时间。
这使得吞吐量固定为0.033OPS,而不管响应时间是多少(假定每个请求的响应时间都小于30秒)。在测试工具中think
time常常是变化的,它们的平均时间大致是某个&#20540;,但是为了更好地模拟用户行为,每个请求的hink time是随机的。除了这个原因,线程调度也不可能是实时的,因此请求之间的真实时间都是有些不同的。因此,即使使用提供cycle
time的工具,测试多次,每次测试的吞吐量也是会有所不同的。
这里有两种不同的方式来测试响应时间。1)平均时间:将每个请求的时间加在一起,除以请求的数目&2)百分点请求(percentile
request),比如:90%请求的响应时间。如果90%的请求响应时间少于1.5秒,10%的请求响应时间大于1.5秒,那么1.5秒就是90%的请求响应时间。上面两种方式的一个区别是极&#20540;对平均&#20540;计算的影响:因为它们被包含在平均&#20540;的计算当中,更大的极&#20540;对平均响应时间的计算影响更大。
下图中20个请求,它们的响应时间分布在不同的范围当中。其中下面的黑粗线是平均响应时间为2.35秒;第一个黑粗线是90%的请求响应时间,这个&#20540;是4秒。
而上图中,90%的请求响应时间为1秒,但是平均响应时间却为6秒,这就是极&#20540;对响应时间产生了巨大的影响。
尽管上面的极&#20540;在实际情况中比较少见,但是对于Java应用却是比较容易发生的,因为GC引入了pause
time。(这里不是说GC会导致100秒的pause
time,而是在测试响应时间很小的应用时,pause time变成了极&#20540;)。在性能测试的时候,我们通常关注90%的请求响应时间(当然95%或99%都是可以)。如果我们只能关注其中一个,百分比请求响应时间是更好的选择,因为百分比请求响应时间更小对绝大多数用户都是有好处的。但是最好两个都要看,请求平均响应时间和至少一个百分比响应时间,以便我们不会丢失有比较大极&#20540;的情况(以便发现问题)。负载生成器:有很多开源和商用的负载生成工具。本书使用Faban,一个开源的,基于Java的负载生成器,它可以用来简单测试一个URL的性能,比如:
上面的例子,使用25个客户端(-c)产生请求到stock
servlet上面(SDO来指示);每个请求有1秒的Cycle
time(-w&1000)。这个测试有300秒的warm-up
period,然后是5分钟的测试,然后是1分钟的ramp-downperiod(&-r
300/300/60)。
理解波动性
第三个原则就是理解每次测试的结果是如何每次都不一样的。处理同样数据集的程序每次都会产生不一样的结果。服务器上的后台进程会影响应用,网络或多或少地会和正在运行的程序进行CPU的竞争等等。一个好的测试方案不会每次让服务端都处理相同的数据集,它们应该产生随机的数据集以便更好地模拟现实情况。但这个会导致一个问题,当对多个测试结果进行比较的时候,是回归了,还是因为测试中各种变化因素导致的?这个问题可以通过多次测试,然后对结果求平均&#20540;来解决。但是问题并不是这么简单,要理解两次测试结果的不同是由于回归还是因为测试中变化因素导致的,这个是非常困难的。
gaoyuan0512
排名:千里之外
(7)(4)(2)(0)(1)(2)(1)(4)(0)

我要回帖

更多关于 java多线程性能测试 的文章

 

随机推荐