Java的秒表类
你应该使用哪个Java类来进行时间性能测量?
(可以使用任何date/时间类,但我要问的原因是.Net中有一个指定的秒表类用于此目的)
Spring框架有一个很好的StopWatch
类 :
StopWatch stopWatch = new StopWatch("My Stop Watch"); stopWatch.start("initializing"); Thread.sleep(2000); // simulated work stopWatch.stop(); stopWatch.start("processing"); Thread.sleep(5000); // simulated work stopWatch.stop(); stopWatch.start("finalizing"); Thread.sleep(3000); // simulated work stopWatch.stop(); System.out.println(stopWatch.prettyPrint());
这产生:
StopWatch'我的秒表':运行时间(毫秒)= 10000 ----------------------------------------- ms%任务名称 ----------------------------------------- 02000 020%初始化 05000 050%处理 03000 030%定稿
java.lang.System.nanoTime()
或者你可以使用在Apache公共版中提供的StopWatch。 这个类使用java.lang.System.currentTimeMillis()
http://commons.apache.org/lang/api-release/org/apache/commons/lang/time/StopWatch.html
检查perf4j。 spring的秒表主要是为了本地的发展。 Perf4j既可以支持您的POCtypes时序,也可以支持生产环境。
这是一个示例,如何使用StopWatch通过注释专用方法来设置多个测量。 使用非常有用和非常简单的方法来测量例如多个embedded式呼叫/操作的服务呼叫等等。
StopWatchHierarchy
package ch.vii.spring.aop; import java.util.Arrays; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.util.StopWatch; @Component public class ProfilingMethodInterceptor implements MethodInterceptor { private static final Logger log = LoggerFactory.getLogger(ProfilingMethodInterceptor.class); public Object invoke(MethodInvocation invocation) throws Throwable { if (log.isInfoEnabled()) { String stopWatchName = invocation.getMethod().toGenericString(); StopWatchHierarchy stopWatch = StopWatchHierarchy.getStopWatchHierarchy(stopWatchName); String taskName = invocation.getMethod().getName(); stopWatch.start(taskName); try { return invocation.proceed(); } finally { stopWatch.stop(); } } else { return invocation.proceed(); } } static class StopWatchHierarchy { private static final ThreadLocal<StopWatchHierarchy> stopwatchLocal = new ThreadLocal<StopWatchHierarchy>(); private static final IndentStack indentStack = new IndentStack(); static StopWatchHierarchy getStopWatchHierarchy(String id) { StopWatchHierarchy stopWatch = stopwatchLocal.get(); if (stopWatch == null) { stopWatch = new StopWatchHierarchy(id); stopwatchLocal.set(stopWatch); } return stopWatch; } static void reset() { stopwatchLocal.set(null); } final StopWatch stopWatch; final Stack stack; StopWatchHierarchy(String id) { stopWatch = new StopWatch(id); stack = new Stack(); } void start(String taskName) { if (stopWatch.isRunning()) { stopWatch.stop(); } taskName = indentStack.get(stack.size) + taskName; stack.push(taskName); stopWatch.start(taskName); } void stop() { stopWatch.stop(); stack.pop(); if (stack.isEmpty()) { log.info(stopWatch.prettyPrint()); StopWatchHierarchy.reset(); } else { stopWatch.start(stack.get()); } } } static class Stack { private int size = 0; String elements[]; public Stack() { elements = new String[10]; } public void push(String e) { if (size == elements.length) { ensureCapa(); } elements[size++] = e; } public String pop() { String e = elements[--size]; elements[size] = null; return e; } public String get() { return elements[size - 1]; } public boolean isEmpty() { return size == 0; } private void ensureCapa() { int newSize = elements.length * 2; elements = Arrays.copyOf(elements, newSize); } } static class IndentStack { String elements[] = new String[0]; public String get(int index) { if (index >= elements.length) { ensureCapa(index + 10); } return elements[index]; } private void ensureCapa(int newSize) { int oldSize = elements.length; elements = Arrays.copyOf(elements, newSize); for (int i = oldSize; i < elements.length; i++) { elements[i] = new String(new char[i]).replace("\0", "| "); } } } }
顾问
package ch.vii.spring.aop; import java.lang.reflect.Method; import org.aopalliance.aop.Advice; import org.springframework.aop.Pointcut; import org.springframework.aop.support.AbstractPointcutAdvisor; import org.springframework.aop.support.StaticMethodMatcherPointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class ProfilingAdvisor extends AbstractPointcutAdvisor { private static final long serialVersionUID = 1L; private final StaticMethodMatcherPointcut pointcut = new StaticMethodMatcherPointcut() { public boolean matches(Method method, Class<?> targetClass) { return method.isAnnotationPresent(ProfileExecution.class); } }; @Autowired private ProfilingMethodInterceptor interceptor; public Pointcut getPointcut() { return this.pointcut; } public Advice getAdvice() { return this.interceptor; } }
ProfileExecution注释
package ch.vii.spring.aop; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Inherited public @interface ProfileExecution { }
注释你的代码
package ch.vii.spring; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import ch.vii.spring.aop.ProfileExecution; @Component public class Bean { @Autowired InnerBean innerBean; @ProfileExecution public void foo() { innerBean.innerFoo(); innerBean.innerFoo2(); innerBean.innerFoo(); } } public class InnerBean { @Autowired InnerInnerBean innerInnerBean; @ProfileExecution public void innerFoo() { } @ProfileExecution public void innerFoo2() { innerInnerBean.innerInnerFoo(); innerInnerBean.innerInnerFoo(); innerInnerBean.innerInnerFoo(); } }
产量
09:58:39.627 [main] INFO cvsaop.ProfilingMethodInterceptor - StopWatch 'public void ch.vii.spring.Bean.foo()': running time (millis) = 215 ----------------------------------------- ms % Task name ----------------------------------------- 00018 008 % foo 00026 012 % | innerFoo 00001 000 % foo 00016 007 % | innerFoo2 00038 018 % | | innerInnerFoo 00000 000 % | innerFoo2 00024 011 % | | innerInnerFoo 00028 013 % | innerFoo2 00024 011 % | | innerInnerFoo 00029 013 % | innerFoo2 00000 000 % foo 00011 005 % | innerFoo 00000 000 % foo
您可以尝试System.currentTimeMillis() ,但是在一些众所周知的IDE(例如eclipse和netbeans)下也有一个很好的分析选项。 另外,远离IDE,您可以在性能测量任务中尝试单独的分析器 。 我认为通过使用分析器,你会得到比使用System.currentTimeMillis()更好的结果。
如果你只是想测量它,使用秒表类,或者也许只是一个秒表。
如果你想让它更快, 考虑这一点 。
最好的是使用System.nanoTime(),但是,如果你想得到Ticks(elapsed Ticks)像System.Diagnostics.Stopwatch那么你需要转换纳秒到Ticks(1 Tick = 100纳秒),然后开始转换毫秒,毫秒,秒,分钟,小时,然后最终将输出格式化为时间表示,例如Elapsed()方法之一(hh:mm:ss.sssssss),但是,看起来像Java中的date仅使用3毫秒(hh:mm:ss.sss),所以你也需要锻炼格式。
我为Java做了一个Stopwatch类,你可以从http://carlosqt.blogspot.com/2011/05/stopwatch-class-for-java.html
例:
package stopwatchapp; import java.math.BigInteger; public class StopwatchApp { public static void main(String[] args) { Stopwatch timer = new Stopwatch(); timer.start(); Fibonacci(40); timer.stop(); System.out.println("Elapsed time in ticks: " + timer.getElapsedTicks()); System.out.println("Elapsed time in milliseconds: " + timer.getElapsedMilliseconds()); System.out.println("Elapsed time in seconds: " + timer.getElapsedSeconds()); System.out.println("Elapsed time in minutes: " + timer.getElapsedMinutes()); System.out.println("Elapsed time in hours: " + timer.getElapsedHours()); System.out.println("Elapsed time with format: " + timer.getElapsed()); } private static BigInteger Fibonacci(int n) { if (n < 2) return BigInteger.ONE; else return Fibonacci(n - 1).add(Fibonacci(n - 2)); } }
输出:
// Elapsed time in ticks: 33432284 // Elapsed time in milliseconds: 3343 // Elapsed time in seconds: 3 // Elapsed time in minutes: 0 // Elapsed time in hours: 0 // Elapsed time with format: 00:00:03.3432284
希望这可以帮助。
private void WaitTimer(long ms) { long t = 0; long x = System.currentTimeMillis(); while(t < ms) { t = System.currentTimeMillis() - x; } }