How to measure exact execution time for a process/method that gets frequently interrupted?

Viewed 121

Currently this is how I get time elapsed for a process to get completed.

long start = System.currentTimeMillis();
process();
long end = System.currentTimeMillis();
long duration = stop - start;
System.out.println(duration);

The problem I am facing currently is the process() gets interrupted(paused) by my pc's hibernation whenever there's no power(My work environment is outside so I have to be on battery) so that it can continue whenever I restart the pc when plugged. I am fully aware I would get a wrong duration if for example I am not able to restart for about 2hrs since the process got paused(during hibernation) as this would mean the extra 2hrs will be accounted for by the CPU clock via the CMOS battery backup whenever the line

long end = System.currentTimeMillis();

is reached. How would it be possible to get the exact duration irrespective of the process being paused severally.

1 Answers

So your question is "how much wall clock time was taken by the process, without time spent in hibernation". Well, wall clock time is easy to get, but you don't really have a chance to know whether hibernation happened or not.

However...

If your process is a set of discrete steps, you could do something like the following

List<Duration> durations = new ArrayList<>();
for(Step step : steps) {
    Instant stepStart = Instant.now();
    process(step);
    durations.add(Duration.between(stepStart, Instant.now()));
}

long totalMillis = durations.stream()
    .mapToLong(Duration::toMillis)
    .filter(ms -> ms < 1000)   // Cut off limit, to disregard hibernate steps
    .sum();

This times each step separately, and if the time for a step takes more than 1 second, it's not taken into account in the total. You could also use an "average" time for those steps, so the end result would be a bit more realistic (of course this depends on the number of steps, the assumed runtime of a single step, etc.).

This only works if there is a good limit to what is "too much" time, and it provides a less accurate result. If you're doing something with BigInteger, it's likely that steps with larger values take more time, so a single cutoff value would not work (although you could consider some kind of dynamic cutoff value, based on the input).

Cheapest, easiest and best solution: run the code on a server.

Related