您的位置:首页 > 运维架构 > 反向代理

性能测量工具类——TimeMeasureUtil & TimeMeasureProxy

2011-10-08 14:28 169 查看
TimeMeasureUtil:做单次时间测量。

1、为了能确保 startTime 和 endTime 都正确设置,因而采用实例对象来实现。每次测量是都能判断对象是否处在正确状态。

2、该类为工具类,即使测试时产生许多对象实例也对软件无任何影响。

public class TimeMeasureUtil {
private long startTime = 0;
private long endTime = 0;

private TimeMeasureUtil(){

}

public static TimeMeasureUtil newInstance(){
return new TimeMeasureUtil();
}

public void start(){
startTime = System.currentTimeMillis();
}

public void end(){
endTime = System.currentTimeMillis();
}

public long measure(){

// Invalid: Before y
if( startTime == 0 ){
throw new IllegalStateException( "Must call metod start() first, when call method measure()." );
}
if( endTime == 0 ){
throw new IllegalStateException( "Must call metod end() first, when call method measure()." );
}
if( startTime > endTime ){
throw new IllegalStateException( "Must call metod start() first, when call method end()." );
}

return endTime - startTime;
}

}


使用示例:

@Test
public void testMeasure_ok() {
TimeMeasureUtil timeUtil = TimeMeasureUtil.newInstance();
timeUtil.start();

// 下面这段代码用实际待测方法代替
try {
Thread.sleep( 1000 );
} catch (InterruptedException e) {
e.printStackTrace();
}

timeUtil.end();

assertEquals( 1000, timeUtil.measure() );
}


由于单次测量可能的偏差太大,没有统计意义,如下类测量平均时间!

TimeMeasureProxy:
1、默认运行20次得平均

2、给定运行次数的平均

缺陷:

1、由于是用反射实现,参数是通过 Object[ ] 来传递。有原始类型(如:byte,int,char...)参数的方法不能测试!只能用 TimeMeasureUtil 来实现测试。 

2、如果第一次执行方法后改变了某属性,而该属性改变后又会影响下一次方法的执行(可能会有不同的时间),这样的方法不能测试。可能的改进方式:先“克隆” count 个该对象,然后用这样相同属性的对象来执行方法(每个对象执行一次方法)。因为这样要求,被测试类提供“克隆”方法,“因测试而影响逻辑”不可取,所以没有实现。

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TimeMeasureProxy {

// default measure count
private int count = 20;

private TimeMeasureProxy(){

}

private TimeMeasureProxy( int count ){
this.count = count;
}

public static TimeMeasureProxy newInstance(){
return new TimeMeasureProxy();
}

public static TimeMeasureProxy newInstance( int count ){
return new TimeMeasureProxy( count );
}

public long avgTime( Object owner, String methodName, Object[] args ){

// valid parameters.
if( owner == null ){
throw new IllegalStateException("owner can't be null.");
}
if( methodName == null ){
throw new IllegalStateException("methodName can't be null.");
}

Class<?> ownerClass = owner.getClass();
Class<?>[] argsClass = null;
if( args != null ){
argsClass = new Class[ args.length ];
for( int i=0 ; i<args.length ; i++ ){
argsClass[i] = args[i].getClass();
}
}

Method method;
try {
method = ownerClass.getMethod( methodName, argsClass );
} catch (SecurityException e) {
throw new RuntimeException( e );

} catch (NoSuchMethodException e) {
throw new RuntimeException( e );
}

return totalTime( owner, method, args)/count;
}

long totalTime( Object owner, Method method, Object[] args ){
long totalTime = 0;

try {
for( int i=0; i<count ; i++ ){
TimeMeasureUtil timeUtil = TimeMeasureUtil.newInstance();
timeUtil.start();
method.invoke( owner, args );
timeUtil.end();
totalTime += timeUtil.measure();
}
} catch (IllegalArgumentException e) {
throw new RuntimeException( e );
} catch (IllegalAccessException e) {
throw new RuntimeException( e );
} catch (InvocationTargetException e) {
throw new RuntimeException( e );
}

return totalTime;
}

}

使用示例:

1、待测试的类

class ForMeasureAvgTime{

public void justForTest(){
try {
Thread.sleep( 335 );
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public void justForTestWithParams( Integer age, String name ){
try {
Thread.sleep( 558 );
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


2、通过TimeMeasureProxy 来测试

@Test
//测量无参数方法&默认次数(20)
public void testAvgTime_defaultCount() {
ForMeasureAvgTime forMeasure = new ForMeasureAvgTime();

TimeMeasureProxy proxy = TimeMeasureProxy.newInstance();
long avgTime = proxy.avgTime( forMeasure, "justForTest", null );

System.out.println( "avgTime=" + avgTime );
assertTrue( (avgTime - 335) < 5 || (335 - avgTime) < 5);
}

@Test
//测量有参数方法&给定次数(10)
public void testAvgTime_giveCount() {
ForMeasureAvgTime forMeasure = new ForMeasureAvgTime();

TimeMeasureProxy proxy = TimeMeasureProxy.newInstance( 10 );
long avgTime = proxy.avgTime( forMeasure, "justForTestWithParams", new Object[]{24, "GongQiang"} );

System.out.println( "avgTime=" + avgTime );
assertTrue( (avgTime - 558) < 5 || (558 - avgTime) < 5);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息