1 概述
在开发中,性能测试是设计初期轻易忽略的问题,开发人员会为了解决一个问题而“不择手段”,作者所参与的项目中也碰到了类似问题,字符串拼接、大量的网络调用和数据库访问等等都对系统的性能产生了影响,可是大家不会关心这些问题,“CPU速度在变快”,“内存在变大”,并且,“似乎也没有那么慢吧”。
有很多商业的性能测试软件可供使用,如Jprofiler、JProbe Profiler等,但在开发当中显得有些遥远而又昂贵。
2 目标
本文将讲述如何利用Java语言本身提供的方法在开发中进行性能测试,找到系统瓶颈,进而改进设计;并且在尽量不修改测试对象的情况下进行测试。
3 预备知识
面向对象编程通过抽象继续采用模块化的思想来求解问题域,但是模块化不能很好的解决所有问题。有时,这些问题可能在多个模块中都出现,像日志功能,为了记录每个方法进入和离开时的信息,你不得不在每个方法里添加log("in some method")等信息。如何解决这类问题呢?将这些解决问题的功能点散落在多个模块中会使冗余增大,并且当很多个功能点出现在一个模块中时,代码变的很难维护。因此,AOP(ASPect Oriented Programming)应运而生。假如说OOP(Aobject Oriented Programming)关注的是一个类的垂直结构,那么AOP是从水平角度来看待问题。
动态代理类可以在运行时实现若干接口,每一个动态代理类都有一个Invocation handler对象与之对应,这个对象实现了InvocationHandler接口,通过动态代理的接口对动态代理对象的方法调用会转而会调用Invocation handler对象的invoke方法,通过动态代理实例、方法对象和参数对象可以执行调用并返回结果。
说到AOP,大家首先会想到的是日志记录、权限检查和事务治理,是的,AOP是解决这些问题的好办法。本文根据AOP的思想,通过动态代理来解决一类新的问题——性能测试(performance testing)。
性能测试主要包括以下几个方面:
l 计算性能:可能是人们首先关心的,简单的说就是执行一段代码所用的时间
l 内存消耗:程序运行所占用的内存大小
l 启动时间:从你启动程序到程序正常运行的时间
l 可伸缩性(scalability)
l 用户察觉性能(perceived performance):不是程序实际运行有多快,而是用户感觉程序运行有多快.
本文主要给出了计算性能测试和内存消耗测试的可行办法。
4 计算性能测试
4.1 目标:
通过该测试可以得到一个方法执行需要的时间
4.2实现:
Java为我们提供了System. currentTimeMillis()方法,可以得到毫秒级的当前时间,我们在以前的程序当中一定也写过类似的代码来计算执行某一段代码所消耗的时间。
long start=System.currentTimeMillis();
doSth();
long end=System.currentTimeMillis();
System.out.println("time lasts "+(end-start)+"ms");
但是,在每个方法里面都写上这么一段代码是一件很枯燥的事情,我们通过Java的java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler利用动态代理来很好的解决上面的问题。
我们要测试的例子是java.util.LinkedList和java.util.ArrayList的get(int index)方法,显然ArrayList要比LinkedList高效,因为前者是随机访问,而后者需要顺序访问。
首先我们创建一个接口
public interface Foo {
public void testArrayList();
public void testLinkedList();
}
然后我们创建测试对象实现这个接口
public class FooImpl implements Foo {
private List link=new LinkedList();
private List array=new ArrayList();
public FooImpl()
{