• MemoryAnalyzer介绍及使用

    Eclipse Memory Analyzer  Tools(MAT)是一个功能丰富且轻量的 Java 堆内存分析工具,可以用来辅助发现内存泄漏减少内存占用。 使用 Memory Analyzer 来分析生产环境的 Java 堆转储文件,可以从数以百万计的对象中快速计算出对象的 Retained Size,查看是谁在阻止垃圾回收,并自动生成一个 Leak Suspect(内存泄露可疑点) 报表。Memory Analyzer 有两种使用方式: 一种是下载独立版本的 MAT, 一种是使用嵌入到 Eclipse 中的 MAT插件。 我这里是用的 eclipse 插件。 如果平时用的是其他 IDE, 可以尝试使用独立版 MAT。 前段时间整理了一下Memory Analyzer相关的内容,包括文档及几个适用案例,目录大致如下: Memory Analyzer使用文档(保存在CSDN); 关于Heap Dump; 使用MAT找出重复引用的jar或类; 使用MAT分析内存泄漏; 找出被空集合占用的内存; 使用MAT分析Java集合的使用。

    [阅读更多...]
  • 使用Memory Analyzer分析Java集合

    上一节里说了如何发现JVM内存中的空集合对象,这对减少JVM内存的浪费有些帮助。这一节要说的内容更有意思一些,可以让我们更深入地了解Java集合的使用。 先说明一点:这里仅仅是通过内存分析来得到一些结论。分析出来的结论通过JDK源码也许可以很轻易地得出,但是请关注分析过程和分析思路,毕竟源码不常有。 在上一节分析空集合对象的过程中难免会产生一些疑问:每个集合的长度有多大?这些集合实例由哪些对象持有?还有一些衍生出的问题:集合空间(capacity)的使用率(或者说填充率)有多高;集合类的hash函数是否足够好;当将元素填充进HashMap实例时是否会发生很多hash冲突?这些都是非常有意义的问题,有助于我们解决具体的任务。在设计开发阶段,这些问题未必都能得到解答,但是在运行测试阶段,借助MAT我们也许可以得到答案。 方案说明 这次会使用MAT中的Query Browser对dump文件进行切面式的分析。Query Browser我们之前已经多次使用,它提供了一系列非常有用的功能,就是这个:。这次主要是用到Java Collections功能组。说一下思路,目前我们有两种方案: 方案一:查询dump中某一个集合类型的全部对象(比如HashMap),然后对结果集进行分组。比如按size进行分组,然后查看size为1的集合对象的持有者。如果您的兴趣在于dump中的全部对象,那么这个方案就值得参考。 方案二:首先缩小要分析的对象的范围,而后使用Java Collection功能组进行分析。举个例子,首先筛选出类名符合“com.zhyea.projects.appname.*”的对象集合,而后在这些对象的histogram视图中再筛选出全部HashMap对象,而后执行查询查看“com.zhyea.projects.appname.*”对象集合中的HashMap对象的size分布信息。如果您的目标是服务器上的某个应用或者是应用中的某个模块,就可以试一下这个方案。 集合对象size 采用哪种结构存储数据以及分配多少初始化空间等内容是在开发阶段决定的,但是用来存储数据的集合对象通常是在运行阶段创建的。因此集合的size以及其持有者通常不是很明确。分析现实场景中得到的dump文件是验证之前采用的方案是否正确的一种方式。通过分析dump文件用户可以知道为集合对象分配的初始空间是否太小或者太大。太小了就会导致集合对象在运行时需要不断的重新调整大小,太大了则会导致不必要的内存浪费。 我取了一份公司测试环境中的dump文件,接下来将使用这份文件演示一下分析的过程。 接下来要做的事就是过滤并显示“com.joyxsys.projects.*”包下类的所有实例。通过执行这个操作我们可以只关注要查看的类,而不受dump中大量的其他对象的干扰。 这个需要用到Query Browser中的Show Retained Set功能: 点击菜单项后,在弹出窗口中输入参数信息: 然后就可以从现有的结果集中进一步过滤出符合“.*HashMap*”的对象: 过滤后的结果: 之后执行右键菜单中的“Collections Grouped By Size”菜单项: 执行菜单项后得到的结果是一个表格。表格的第一列是HashMap对象的大小,第二列是这样大小的HashMap对象的数量,再就是对应组中对象的Shallow Size和近似Retained Size: 如果对其中的某组数据感兴趣(比如长度为0的这组数据)就可以使用“Immediate dominators”这个菜单项来找出是谁持有这个组中的对象: 就如之前的经验,在这个面板中我们会看到一些类: 通过分析我们可以看到,在我的应用中共有104个HashMap对象,其中size为0的对象有93个。DelegatingClassLoader持有了90个size为0的HashMap对象。 集合填充率 “Collection Fill Ratio(集合填充率)”查询和刚才执行的查询在某种程度上很类似。不同之处在于Fill Ratio查询只对会为元素预先分配空间的集合类型有效,比如HashMap、ArrayList等等。Fill Ratio查询得到的信息是预分配空间的使用率,这个值通常在0~1之间,计算公式是 Fill Ratio = size / capacity。 对“com.joyxsys.projects.*”包下的HashMap实例执行Collection Fill Ratio: 查询结果如下图: 可以看到在104个HashMap实例中,93个是空的(和上面得到的结果一致),还有9个Fill Ratio不到20%。所有实例中Fill Ratio最高也不过40%。当然本身数据的总量就不够大,因此也说明不了多少问题。 通常可以把上面提到的两种方式结合起来分析问题。比如可以先执行”Collections Fill Ratio”,而后在得到的分组结果基础上执行”Collections Grouped By Size”操作。 Hash效率 现在开始讨论下一个问题——hashMap和Hashtable中的hash冲突。一个不甚高明的hash()方法实现会严重影响哈希表的查找速度。最为极端的一种情况就是所有元素返回的hash值都是一样的,这样每次查找就相当于遍历一个LinkedList。 哈希函数是否会导致太多哈希冲突也是一个在开发阶段不容易得到验证的问题,但同时也是通过分析dump文件容易得到结果的一个典型案例。尽管这问题和性能相关更多,但还是在dump中留下了相当多的痕迹,我们可以借助”Map Collision Ratio”来解决这个问题。通过”Map Collision Ratio”可以对HashMap(或Hashtable)的实例按哈希冲突的概率进行分组。哈希冲突的概率是向hash表中插入Entry时发生哈希冲突的概率。 仍然是分析刚才的dump文件,不过这次直接查看全部的HashMap实例,打开Histogram视图,过滤HashMap实例,之后再执行“Map Collision Ratio”查询: 执行查询后会得到一个表格,其中第一列是Collision Ratio,第二列是相应的对象的数目。 在这里可以很清楚地看到只有一个实例的Collision Ratio介于60%到80%之间。现在可以看一下这个实例,以及发生冲突的所有的key。首先要尝试获取相关的实例: 执行结果: 在这个里面是看不出什么来的,因为key的类型是String。关于String的hash函数是否够好我想不需多说。但是为什么还会出现这样的情况呢,我能想到的一个解释就是太巧了,碰巧大部分元素都是相同的hash函数。这样的一个HashMap实例会呈现出什么样的特点呢:就是会出现一个非常长的链表,hash表中几乎80%的元素都会在这个链表中。这个可以通过“Grouped By Size”和“List Objects”这两个工具来分析一下。 查看HashMap内容 最后介绍一个可以方便查看Map结构内容的工具:“Hash Entries”。在做性能分析工作时这个工具将会经常用到。 通过“List Objects”查看HashMap实例内容通常都不是一件容易的事情,关键是太容易受到干扰了,一大堆内容同时出现,尤其是Hash冲突比较严重的时候,需要不停的展开折叠内容。 看看上面这张图体验一下。 这时可以使用“Hash Entries”对一个或多个hashMap实例进行查询,查询结果依然是一个表格: 这时候是不是看起来舒服多了。现在可以使用右键菜单继续对目标实例进行分析了。 分析数组 在“Java Collections”功能组还提供了两个数组分析的工具(功能和我们前面介绍的类似,所以不会再重复说明了): Arrays Grouped By Size:对直接类型数组和对象数组都有效; Array Fill Ratio:对直接类型数组无效,统计数组中值不为null的元素的比例。 参考文档 Analyzing Java Collections Usage with MAT:http://scn.sap.com/people/krum.tsvetkov/blog/2007/11/05/analyzing-java-collections-usage-with-memory-analyzer

    [阅读更多...]
  • 找出被空集合占用的内存

    在平时的内存分析中发现有很大一部分集合对象在实例化后就从没有被使用过。集合类是我们平时使用最多的一种类,部分集合类在实例化时就会得到一部分空间(比如ArrayList、HashMap等)。这些空的集合实例虽然价值不大,但也有可能会浪费很多的内存空间。接下来演示一下如何去发现并解决这个问题。 案例 看一下下面这个MyValueStorage类的代码,在这个类里定义了三个ArrayList型的成员变量,并做了初始化操作。这个三个成员变量中standardValues将会被经常用到,specialValues偶尔会被用到,erroneousValues只有在极少数的情况下(比如发生异常)才会被使用到。 一个空的ArrayList默认初始化capacity是10,在32位操作系统上会占用80byte的内存空间,在64位操作系统上则会占用144byte。假使这个类在系统中被广泛的使用,在内存中有接近500 000个实例。那么在32位的系统中将会为specialValues和erroneousValues保留80 M的空间(在64位系统上是144MB)。一个应对的思路就是延迟初始化,即直到使用这些对象的时候才将之实例化,否则一直为null。当然我们需要做一些额外的工作,比如添加几个“if”语句以避免空指针异常的出现。 换个角度来考虑这个问题:如果对象的实例不多的话,那么为之进行优化的工作就是没有必要的。所以在着手优化之前,需要先弄清楚优化工作是否可以获取到明显的收益,在我们这个例子里就是是否可以显著地节省内存。 怎样找出未使用的集合实例 要找出未使用的集合实例可以遵循如下的步骤: 正常运行实例一段时间,根据线程ID获取heap dump文件; 使用Memory Analyzer中的OQL(Object Query Language)工具来查找大小是0且修改次数也是0的集合对象。即在我们获取dump文件之前,这些集合对象一直是空的且从未被修改过。 点击工具栏上的“OQL”按钮启动OQL工具: 顾名思义,OQL类似于SQL语句。这里我们使用如下的语句检查是否有空的且从未被使用过的 ArrayList, HashMap和Hashtable实例: 点击工具栏的红色叹号按钮执行查询。注意一次执行一行。 要想了解更多关于OQL的细节可以参考官方文档。此外,这篇文也不错,先将就着看,有时间整理一下。 计算空集合占用的内存 OQL查询得到的结果是一个符合查询要求的对象列表。想知道这些对象一共占用了多少内存可以开启histogram(直方图)视图。 然后计算所有对象占用的内存总量(使用工具栏上的“Calculate Retained Size”按钮,也可以在右键菜单中找到相关项),在下图实例中是266.4KB,还不算大。 这些空集合在哪儿 在确定了空集合的大小以后,如果发现有必要去做一些优化,那么接下来的事情就是找出谁制造了这些空集合。一个最快捷的方式就是使用右键菜单中的“Immediate Dominators”项。 结果如下图: 看到了这个结果以后相信会比较容易定位到需要优化的位置。对于我这个应用来说是然并卵——大部分都在框架上,幸好占用的空间不大,还不需要优化。 就这样!! 参考文档 Memory For Nothing:http://scn.sap.com/people/krum.tsvetkov/blog/2007/08/02/memory-for-nothing Analyzing a Heap Dump Using OQL:http://visualvm.java.net/oqlhelp.html ########

    [阅读更多...]
  • 使用Memory Analyzer分析内存泄漏

    概述 检测内存泄漏通常采用的方式是检查内存中某些对象的数量是否存在单调递增的现象。这可以通过“在线”实时监控分析的方式或者比较不同时段的内存快照来实现。然而实时监控的方案通常并不可行,尤其是在生产环境上,得考虑到因此导致的性能消耗;并且内存泄漏的产生通常也是非常偶然的,只有在某些特定条件下才会发生。这篇文章将介绍一些使用MAT发现内存泄漏的技巧。 准备工作 首先一定要有足够的数据,这里指的是heap dump文件。可以对JVM进行配置,以实现一发生OutOfMemoryError就自动生成Heap Dump文件。 第二步就是让内存泄漏问题清楚地暴露出来从而容易被捕捉到。这里有一个技巧:试着调整一下应用运行时的最大堆内存,调整到比应用正常运行所需的内存大一些就可以了(建议是一次Full GC后剩余内存的两倍大小)。即使不知道应用运行时到底需要多大的内存,加大堆内存也不是一个坏主意(有时可能真的就是内存不够用了,而非是发生了内存泄漏)。这里不讨论分配给一个应用太大的堆内存是好还是坏——这里只是将调整内存作为故障排除的一个临时方案。调整内存后我们会得到什么呢:如果确实存在内存泄漏,和内存泄漏有关的对象的大小估计会占到堆内存的一半(如果当时设置的是两倍),此时再找导致内存泄漏的原因应该就比较容易了。 案例一 现在假设我们已经做好了配置,然后某一天发生了MMO错误并生成了一个相当大的heap dump文件。接下来该怎么做呢?说实话,接下来要做的事情非常简单。 首先使用MAT打开这个heap dump文件。如果文件非常大的话,第一次打开可能会需要等一段时间,之后再打开这个文件就会非常快了,因为首次打开的时候已经完成了对文件的解析。现在开始尝试找出到底是谁蚕食了我们的内存。点击工具栏上的按钮进入Dominator tree视图: 这里会看到首页的对象图以一个树的形式展现出来。这个树里展示了对象、依赖、它们之间的引用关系以及其他。这里不会详细介绍这个树背后的全部细节,只是说一下两个重要的指标: 在树的最顶端(依Retained Heap Size排序)可以看到内存中最大的对象; 最大的对象就是占用内存最多的对象,它在树中的子节点都是被该对象直接或间接引用的对象(这意味着当这个对象被回收的时候它的子节点对象也会被回收)。 一般发生内存泄漏的时候,都会直接锁定那个最大的对象。接下来一步步接近真相:展开最大对象的子树,试着找到retained size最接近最大对象的子节点(通常是一个数组或者集合)。就是这么简单,我们找到了内存泄漏的元凶。如果还想继续探索下去的话,可以尝试探索更深的子节点。 看一下展开后的结果: 下一件事就是找到内存泄漏的对象到GCRoots的引用链。选中内存泄漏对象,右键菜单中选择“Paths from the GC roots -> without weak and soft references”即可: 在“Paths from the GC Roots”可以看到我们选中的对象到GCRoot的路径,最顶端是我们选中的目标,最下方是GCRoots。选的样本不好,估计到GCRoot还得展开好久: 换了一个样本,这下清晰多了: 案例二 如果所有的问题都能像上面的案例那样容易解决就太好了。有时候仅仅看一次dominator tree是远远不够的。看看下图的案例:这里也提供了足够多的内存让内存泄漏对象去生长,也打开一个覆盖了所有对象的dominator tree,其中就包括内存泄漏对象。但是能看到内存泄漏对象么?在案例一中,所有小的内存泄漏对象都被一个巨大的根对象引用,但是有时候这些相对较小的内存泄漏对象就直接在dominator tree的顶级节点上。尽管这些小的内存泄漏对象数量很多,但是每个对象的Retained Size都比较小,因此不会排在前面。 此时点击工具栏中的“Group by class”按钮会有很大的帮助: 点击按钮后,我们可以看到同一组对象Size的总和,此时再找内存泄漏的原因是不是会更容易一些: 其他 附上测试程序: 模拟时使用的虚拟机参数: 参考文档 Finding Memory Leaks with SAP Memory Analyzer Shallow heap & Retained heap

    [阅读更多...]
  • 使用MAT找出重复引用的jar或类

    这篇文章将介绍一种处理应用中的类(或库)的重复引用以及版本冲突问题的解决方案。这在应用集成阶段非常有效。适用于如下案例: NoClassDefFoundError:在classpath中有两个不同版本的同名类; 集成大型产品:检查同一个版本的jar包是否被重复引入,减少内存占用。 准备工作 安装Memory Analyzer Tools,在eclipse上搜mat插件、百度搜索、谷歌搜索都可以。 获取heap dump文件,参考这里:《关于Heap Dump》 步骤 使用MAT打开dump文件,执行Open Query browser->Java basics->Duplicated classes,如下图: 现在我们可以看到所有重复的类及相关的类加载器了: 需要注意的是:相关的类必须是被加载过才能找得到。 一个小技巧 既然我们已经做到这里了,顺便给您展示一下另外一个小tip。通过Inspector视图,可以看到被加载的类具体是在哪个jar包里。举例说,如果一个重复的类是被URLClassloader加载的,只需按以下的步骤执行: 选择目标类; 通过类属性页签进入Inspector视图; 右键点击“_context”属性; 最后点击“Go Into”。 在弹出的窗口窗口中,可以看到属性“_war”,然后就是被加载的类的位置了: ###### 本文译自下文:http://community.bonitasoft.com/blog/effective-way-fight-duplicated-libs-and-version-conflicting-classes-using-memory-analyzer-tool

    [阅读更多...]
  • 在命令行执行JMeter测试计划

    有时候会需要在linux的命令行上运行JMeter,简单说一下做法: 在图形界面上创建测试计划,并保存生成的test_plan.jmx文件; 将生成的test_plan.jmx文件上传到linux服务器; 在linux的命令行执行如下指令: 其中-n说明不是在图形界面下执行,-t指示了测试计划文件的位置。 还是写一个简单的示例吧。接下来创建一个HTTP请求的测试计划。 创建测试计划: 添加一个监听器: 这里将监听结果保存到文件。因为没办法直接通过图形界面查看运行结果,需要通过文件查看监听结果。 最后在命令行执行测试计划: 执行结束后可以将执行结果文件拷贝出来,在jmeter中打开查看。

    [阅读更多...]
  • 使用JMeter + PerfMon做远程监控

    本文假设已经安装好了JMeter 下载插件 PerfMon并不是JMeter原生的工具。要使用这个工具还需要下载一些插件。下载地址是jmeter-plugins.org。在JMeter Plugins的下载页面可以看到如下需要下载的内容: 下载用红框圈起来的前两个压缩包即可。 下载完成后。将第一个压缩包JMeterPlugins-Standard-1.3.1.zip解压到JMeter的安装目录下。第二个压缩包ServerAgent-2.2.1.zip解压后可以放在要监控的服务器上的任何位置。 使用 将第二个压缩包解压后,目录下有两个启动文件startAgent.sh和startAgent.bat。视平台选择启动文件启动PerfMon。 打开JMeter,添加线程组,在线程组下添加监听器jp@PerfMon Metrics Collector。 然后在PerfMon Metrics Collector中按自己的需求稍作配置即可。 此时照说是应该配置完了。我在官网和其他的地方找到的一些文章也说就这样就可以了。但是坑爹的是,做一下就会发现只这样还是不行的——一运行就会退出。我们还需要添加一个采样器Sampler。什么采样器都行,有了采样器就不会一点运行就退出。 关于怎么使用JMeter这里说的非常简略。想要多了解些可以看一下下文中的参考文档。这里不想反复说一些大家都知道的内容,只是稍作补充并略述心得而已。 最终还是发现PerfMon不是一个好的监控方案。因为CPU的消耗太大,一启动就会占用84%的CPU。用着真心不好,可以替代的方案也太多了,比如jvisualvm。 ######### 参考文档 JMeter Plugin官网: http://jmeter-plugins.org/ JMeter 服务器性能监测插件介绍:http://blog.csdn.net/defonds/article/details/41650813 Jmeter测试工具:http://www.cnblogs.com/zhangchaoyang/articles/2530731.html

    [阅读更多...]
  • 基于JMeter进行分布式测试

    我工作中的笔记本配置还可以。但是在测试一个简单的TCP连接时,发现把线程数设置为10000时,我的笔记本会很快死掉。最终实验出我的笔记本可以承受的安全线程数是5000。可是对应用的最低性能要求就是能承受1w的并发。此时可以采用基于JMeter的分布式测试方案。 如刚才提到的,要求测试应用在1w并发下的表现,而一部计算机所能承受的线程数是5000,那么需要两部计算机。 步骤 具体步骤如下: 为两部机器都安装JMeter; 定义两部机器的角色,一部是master,一部是slave;我们直接操作master,而slave只是负责分担master的压力; 获取slave的ip地址,比如是192.168.1.12; 在master的JMeter目录下打开bin目录,编辑jmeter.properties文件。找到“remote_hosts=127.0.0.1”这一行,将之修改为“remote_hosts=127.0.0.1,192.168.1.112:1099”。其中1099是master和slave的RMI通信端口。编辑完后记得保存; 打开master上的JMeter,点击运行菜单项,运行->远程启动->选择要启动的slave的IP;如果需要全部启动,运行->远程全部启动即可。 注意事项 有几点需要注意: 1. 启动jmeter-server服务时,提示: 这个是开始没有找到ApacheJmeter_core.jar,后来去JMETER_HOME目录下去查找,最后找到了,如果不希望看到Could not find的字样,可以配置一下jmeter_home的路径(即bin目录的上一级目录),这样启动jmeter-server服务时,就只会看到Found ApacheJMeter_core.jar,当远程访问时,会看到控制台上打印出一行:Starting the test on host [ip]:1099 @….(大概是这样的,@后面是执行开始的时间),远程执行结束,会打印一行:Finished the test on host [ip]:1099 @…,表示远程执行结束。 2. 留意一下1099端口,目前暂未确定这个端口是不是可以改的(按理说这个是可以从配置文件中修改的,目前还没有找到如何修改Agent上面的配置,Controller上面的还好修改) 3. Jmeter分布式控制过程中,各个Agent启动的线程数等于线程组中的配置,不是均分线程组中的配置。 参考文档 http://blog.chinaunix.net/uid-26884465-id-3419474.html http://www.51testing.com/html/12/252512-223613.html

    [阅读更多...]
  • JMeter监听器说明

    JMeter的监听器可以理解为JMeter提供的测试分析工具(或者测试结果报告)。JMeter监听器的监听范围是当前节点及其子节点。JMeter提供了多种测试监听器,这里简单说几个用过的监听器。 创建测试计划 为了演示监视器的作用,我这里做了一个简单的HTTP请求测试。 如何创建测试计划就不多说了,可以参看这篇文章:《使用JMeter》 下图是线程组的配置: 下图是HTTP请求的配置参数: 启动测试,很快就可以生成测试结果报告。 用表格查看结果 下图是表格结果: 还有几个重要的指数: 简单说下表格中的字段: Sample#——每个请求的ID; StartTime——每个请求启动时间; SampleTime——响应每个请求的时间(以毫秒为单位); Status——请求状态,如果为勾则表示成功,如果为叉表示失败; Bytes——请求的字节数; Latency——延迟时间; ConnectTime——请求连接用时。 几个指数: 样本数目——样本总数(线程数*循环次数),或者说是发送给测试应用的请求总数; 最新样本——服务器响应最后一个请求的时间; 平均——请求响应时间的平均值; 偏离——请求响应时间的标准差。 聚合报告 下图是本次测试的聚合报告: Label——取样器名称; Samples——发给被测试应用的请求总数; Average——请求响应时间的平均值; Median——请求响应时间中值,即50%的请求响应时间都小于该值(一个统计学的概念); 90%Line——请求响应时间90%线,即90%的请求响应时间都小于该值; Min——最小响应时间; Max——最大响应时间; Error%——出错率(出错的请求数/所有的请求数); Throughput——吞吐量,每秒/每分钟(具体看“/”后面的单位)处理的请求数; KB/sec——每秒从服务器端接收到的数据量,相当于LoadRunner中的Throughput/Sec; 【注意】总体值并不是各列对应记录的累加。是以所有Samples为样本的统计值,如:总体Min=min{各个Samples的Min},总体Max=max{各个Samples的Max}。 Summary Report(总结报告) 下图是本次测试的Summary Report: 觉得这个和聚合报告一起看有点意思。 Label——取样器名称; Samples——发给被测试应用的请求总数; Average——请求响应时间的平均值; Median——请求响应时间中值,即50%的请求响应时间都小于该值(一个统计学的概念); 90%Line——请求响应时间90%线,即90%的请求响应时间都小于该值; Min:最小响应时间; Max:最大响应时间; Std.Dev——所有请求响应时间的标准差,即是“用表格查看结果”中的偏离; Error%——出错率(出错的请求数/所有的请求数); Throughput——吞吐量,每秒/每分钟(具体看“/”后面的单位)处理的请求数; KB/sec——每秒从服务器端接收到的数据量,相当于LoadRunner中的Throughput/Sec; Avg.Bytes——服务端返回给Request数据的平均值(服务端返回所有数据/请求数)。 图形结果 本次测试的图形结果如下图: 这里的几个指数上面都有提到。还是再说一次吧: 样本数目——样本总数(线程数*循环次数),或者说是发送给测试应用的请求总数; 最新样本——服务器响应最后一个请求的时间; 平均——请求响应时间的平均值; 偏离——请求响应时间的标准差; 吞吐量——每秒/每分钟(具体看“/”后面的单位)处理的请求数; 中值——请求响应时间中值,即50%的请求响应时间都小于该值。 查看结果树 下图是查看结果树: 简单说几个概念: 取样器结果——显示的是请求样本相关参数(客户端参数与响应参数) 请求——发送请求的具体值 响应数据——服务端返回的相应参数 ALL! 参考文章 http://www.51testing.com/html/12/252512-223091.html http://www.cnblogs.com/jackei/archive/2007/01/17/623166.html http://www.cnblogs.com/Carrie_Liang/archive/2008/11/10/1330997.html http://zuoye.baidu.com/question/1d937880d6e95b419397e16b267a71ba.html

    [阅读更多...]
  • 使用JMeter

    JMeter是一款基于java开发的压力测试应用。最初是为测试 Apache JServ(tomcat的前身)的性能而开发的。不久以后,JMeter也成为了jakarta的一个子项目。 安装 截至目前(20150408),JMeter最新的版本是2.13。用户可以在JMeter官网下载最新的稳定版本。官网提供了.zip和.gz两种格式的下载文件。JMeter2.13需要JDK1.6或更高版本的环境。 下载解压完成后,可以尝试启动jmeter。在linux环境下,运行bin目录下的jmeter脚本,在windows环境下,需要调用jmeter.bat文件。建议将bin目录添加到系统环境变量下,以便调用。下图是JMeter的主窗口: 可以看到,整个界面分为两部分。左侧是测试中需要使用的元素,包括测试计划和工作台。在这篇文章里,我们主要说说测试计划的使用。右键点击测试计划(或工作台),可以添加新的测试计划(或工作台)元素。右键点击新增的测试计划(或工作台)内容,可以选择将之删除。右侧面板则展示了测试计划或工作台的详细信息。 现在可以准备使用JMeter了,但是有两点需要注意: 不可以将JMeter和被测试的应用在同一台机器上运行。因为JMeter会占用大量的系统资源,如果被测试的应用在同一台机器上的话,应用的性能会受到影响; 尽量避免测试受到网络因素的影响。最好可以让网络管理员建立一个隔离的子网络来运行JMeter和被测试的应用。 一个简单的测试 首先,我们进行一个非常简单的测试。在这个测试里,我们将建立一个测试计划,并对一个web应用进行测试。通过这个测试,你可以了解到JMeter的一些常用概念,并基本掌握使用JMeter进行测试的能力。 在实施测试前,我们需要先创建一个测试计划。测试计划描述了使用JMeter进行测试的步骤。一个测试计划包括一个或多个线程组、逻辑控制器、配置元件、定时器、前置处理器、后置处理器、Sampler、断言、监听器等等。如果不懂这些东西是做什么的,先不要担心,我们会在后面的部分说清这些元素的用法。 一个测试计划需要有至少一个线程组。线程组是测试计划实施的起点,它可以包含JMeter实施测试的其它元素。在测试中,线程组负责控制JMeter模拟的用户线程。 现在我们从创建线程组开始。右键点击测试计划,添加->Threads(Users)->线程组,这样就可以在测试计划下新增一个线程组元素了。点击新建的线程组,可以看到下图: 简单介绍下面板中的几个属性: 名称——线程组的名字。可以用一个简短的名称来描述线程组,也可以在注释中给它添加说明; 线程数——JMeter创建的线程数。每个线程代表一个用户。如果想测试10个用户同步操作,那么输入10; Ramp-Up Period——这里标识JMeter创建所有的线程所需要的时间,时间单位是秒。如果线程数是10,Ramp-Up Period是20秒,那么就表示JMeter将在20秒内创建10个线程,即每2秒创建一个线程。如果要20个线程立刻创建完成的话,那么输入0; 永远——如果勾选的话,这个选项会使JMeter无限次地发送请求给被测试应用。如果不勾选的话,那么JMeter只会重复发送指定循环次数的请求; 循环次数——这个属性只会在“永远”复选框没有勾选的情况下发挥作用。这个属性是用来告诉JMeter循环发送多少次请求。 在我们这个小测试中,按照下图来填充测试时的属性。我们模拟了两个用户,每个用户会发送三次请求。这次我们使用了几个非常小的数,这是为了方便我们接下来解释测试结果。在真正的测试环境中,我们更喜欢使用一些很大的数字。 接下来,我们将添加一些测试HTTP 请求的元素。右键点击线程组,添加->Sampler->HTTP请求,这样就添加了一个HTTP请求元素。点击“HTTP请求”,可以看到如下图所示的界面: 在“HTTP请求”面板上,可以设置HTTP请求的参数。这里,有如下几个属性: 名称——HTTP请求的名称。名称需要有足够的代表性,要知道一个线程组中一般会有多个HTTP 请求; 服务器名称或IP——测试应用所在的主机名称或IP地址; 端口号——测试应用所占用的端口号; 协议——所使用的协议,如HTTP或HTTPS; 方法——请求方法,如GET或POST; 路径——资源请求的路径; 跟随重定向——如果有重定向的话是否跟随; Use KeepAlive——如果勾选的话,在请求头中将会包含“Connection = Keep-Alive”;一般的浏览器,在使用HTTP1.1协议发送请求的时候会默认使用“Connection = Keep-Alive”作为连接头。因此,这个复选框一般都会被勾选上; Parameters——请求中所发送的参数列表,可以使用添加、删除按钮添加或删除参数; 同请求一起发送文件——模拟文件上传。 现在,弄清“HTTP请求”中的配置参数了吧。我们还有最后一个要添加到ThreadGroup中的元素,就是监听器。监听器在JMeter中的作用类似于报表。JMeter提供了多种报表,包括图形报表和表格报表。在这次测试中,我们使用最简单的表格报表。右键点击线程组元素,添加->监听器->用表格查看结果,添加表格报表。 好了,一切就绪,可以运行我们的测试计划了。在这之前还有最后一个忠告:在执行测试计划前一定要先保存测试计划,因为JMeter有可能会导致系统崩溃(在线程和循环次数较多的情况下可能会发生这样的情况)。现在,点击绿色的启动按钮运行我们的测试计划吧。 在测试计划运行期间,工具栏右侧有个小方块会变成绿色(有时需要将窗口最大化)。 因为一个测试不会无限期的执行下去,当测试计划执行完毕时,JMeter会自动将之关闭。若JMeter无法自动关闭测试,就需要我们做出干预。点击红色的停止或关闭按钮,关闭所有的连接,结束当前的测试计划。 运行我们的测试计划,得到的结果如下图: 表格中的信息还是比较容易理解的。一共产生了6个测试样本(2个线程,3个循环次数,2*3=6)。表格的第6列标识所有的样本都已测试成功。表格的第5列是样本响应时间,分别是33,32,11,11,10,10。平均响应时间是(33+32+11+11+10+10)/6 = 17(这里是向下取整)。 另外一个重要的指数是偏离度。偏离度是每个样本的响应时间与平均值之间偏差的平方之和的平方根(有点绕,实际上就是标准差,可以据此分析离散性,概率论相关概念)。这个数值标识了被测试应用的稳定性。如果偏离度比较高的话,说明一部分用户会得到非常快速的响应,而另一部分用户却会等上很长的时间。总之,偏离度这个值是越小越好。 练习了这样一个简单的测试后,也就可以从容应对一些复杂的测试了。在进行Web应用的压力测试时,可以逐步提高线程数和循环数,以便观察被测试应用是怎样应对高负载压力的。 接下来的几节将说明一些使用JMeter进行压力测试的一些比较重要的内容。 监听器 JMeter提供了多种监听器(或者说是报表)。在刚才的测试中,我们使用了表格来展示测试结果。如果表格报表不能满足需求的话,还可以为线程组选择一个或者多个监听器。其中比较常用的一个监听器是“图形结果”,如下图所示: 复合HTTP请求 一个web应用可能同时包含静态的和动态的资源。如果想查看这些资源的性能,JMeter可以很轻松地实现发送复合式的HTTP请求。实现这个测试,只需要添加一定数目的“HTTP请求”元素,并分别进行配置即可。当建立了多个HTTP请求元素时,你可能会希望为所有的HTTP请求创建默认值,下一节会说明如何建立HTTP请求默认值元素。 HTTP请求默认值 右键点击线程组元素,添加->配置元件->HTTP请求默认值,添加HTTP请求默认值元素。正如其名,HTTP请求默认值元素指定了同一个线程组下所有的HTTP请求元素的配置参数默认值。HTTP请求默认值是一个非常有用的元素。在绝大多数情况下,HTTP请求总会有些相同的配置参数属性,比如服务器和端口。 HTTP Cookie 管理器 许多web应用都使用了cookie。JMeter通过HTTP Cookie管理器提供了cookie管理功能。在线程组中添加了cookie管理器后,就可以像浏览器一样发送cookie信息了。右键点击线程组元素,添加->配置元件->HTTP Cookie 管理器,可以添加HTTP Cookie管理器,下图是cookie管理器的配置页: 总结 这次我们只是做了一个十分简单的测试,而使用JMeter能做的事情远远不止这些。通过我们提到的这些元素,可以使用JMeter进行各种测试并取得详尽的测试结果报告。这样得到有价值的结果也很容易了。 OK! 本文是翻译的一篇英文文章。难免有词不达意的地方,还请见谅。 原文在这里:http://www.onjava.com/pub/a/onjava/2003/01/15/jmeter.html 还有,这是JMeter的用户手册,虽然说得比较简略,可还是聊胜于无:http://jmeter.apache.org/usermanual/index.html

    [阅读更多...]