How do I measure time elapsed in Java?
Unfortunately, none of the ten answers posted so far are quite right.
If you are measuring elapsed time, and you want it to be correct, you must use System.nanoTime()
. You cannot use System.currentTimeMillis()
, unless you don't mind your result being wrong.
The purpose of nanoTime
is to measure elapsed time, and the purpose of currentTimeMillis
is to measure wall-clock time. You can't use the one for the other purpose. The reason is that no computer's clock is perfect; it always drifts and occasionally needs to be corrected. This correction might either happen manually, or in the case of most machines, there's a process that runs and continually issues small corrections to the system clock ("wall clock"). These tend to happen often. Another such correction happens whenever there is a leap second.
Since nanoTime
's purpose is to measure elapsed time, it is unaffected by any of these small corrections. It is what you want to use. Any timings currently underway with currentTimeMillis
will be off -- possibly even negative.
You may say, "this doesn't sound like it would ever really matter that much," to which I say, maybe not, but overall, isn't correct code just better than incorrect code? Besides, nanoTime
is shorter to type anyway.
Previously posted disclaimers about nanoTime
usually having only microsecond precision are valid. Also it can take more than a whole microsecond to invoke, depending on circumstances (as can the other one), so don't expect to time very very small intervals correctly.
Which types to use in order to accomplish this in Java?
The short answer is a long
. Now, more on how to measure...
System.currentTimeMillis()
The "traditional" way to do this is indeed to use System.currentTimeMillis()
:
long startTime = System.currentTimeMillis();
// ... do something ...
long estimatedTime = System.currentTimeMillis() - startTime;
o.a.c.l.t.StopWatch
Note that Commons Lang has a StopWatch class that can be used to measure execution time in milliseconds. It has methods methods like split()
, suspend()
, resume()
, etc that allow to take measure at different points of the execution and that you may find convenient. Have a look at it.
System.nanoTime()
You may prefer to use System.nanoTime()
if you are looking for extremely precise measurements of elapsed time. From its javadoc:
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
Jamon
Another option would be to use JAMon, a tool that gathers statistics (execution time, number of hit, average execution time, min, max, etc) for any code that comes between start() and stop() methods. Below, a very simple example:
import com.jamonapi.*;
...
Monitor mon=MonitorFactory.start("myFirstMonitor");
...Code Being Timed...
mon.stop();
Check out this article on www.javaperformancetunning.com for a nice introduction.
Using AOP
Finally, if you don't want to clutter your code with these measurement (or if you can't change existing code), then AOP would be a perfect weapon. I'm not going to discuss this very deeply but I wanted at least to mention it.
Below, a very simple aspect using AspectJ and JAMon (here, the short name of the pointcut will be used for the JAMon monitor, hence the call to thisJoinPoint.toShortString()
):
public aspect MonitorAspect {
pointcut monitor() : execution(* *.ClassToMonitor.methodToMonitor(..));
Object arround() : monitor() {
Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString());
Object returnedObject = proceed();
monitor.stop();
return returnedObject;
}
}
The pointcut definition could be easily adapted to monitor any method based on the class name, the package name, the method name, or any combination of these. Measurement is really a perfect use case for AOP.
Your new class:
public class TimeWatch {
long starts;
public static TimeWatch start() {
return new TimeWatch();
}
private TimeWatch() {
reset();
}
public TimeWatch reset() {
starts = System.currentTimeMillis();
return this;
}
public long time() {
long ends = System.currentTimeMillis();
return ends - starts;
}
public long time(TimeUnit unit) {
return unit.convert(time(), TimeUnit.MILLISECONDS);
}
}
Usage:
TimeWatch watch = TimeWatch.start();
// do something
long passedTimeInMs = watch.time();
long passedTimeInSeconds = watch.time(TimeUnit.SECONDS);
Afterwards, the time passed can be converted to whatever format you like, with a calender for example
Greetz, GHad