There is a question which was recently asked to me in an interview.
Problem: There is a class meant to profile the execution time of the code. The class
I'm going to suggest that enforcing the method call sequence is solving the wrong problem; the real problem is a unfriendly interface where the user must be aware of the state of the stopwatch. The solution is to remove any requirement to know the state of the StopWatch.
public class StopWatch {
private Logger log = Logger.getLogger(StopWatch.class);
private boolean firstMark = true;
private long lastMarkTime;
private long thisMarkTime;
private String lastMarkMsg;
private String thisMarkMsg;
public TimingResult mark(String msg) {
lastMarkTime = thisMarkTime;
thisMarkTime = System.currentTimeMillis();
lastMarkMsg = thisMarkMsg;
thisMarkMsg = msg;
String timingMsg;
long elapsed;
if (firstMark) {
elapsed = 0;
timingMsg = "First mark: [" + thisMarkMsg + "] at time " + thisMarkTime;
} else {
elapsed = thisMarkTime - lastMarkTime;
timingMsg = "Mark: [" + thisMarkMsg + "] " + elapsed + "ms since mark [" + lastMarkMsg + "]";
}
TimingResult result = new TimingResult(timingMsg, elapsed);
log.debug(result.msg);
firstMark = false;
return result;
}
}
This allows a simple use of the mark
method with a result returned and logging included.
StopWatch stopWatch = new StopWatch();
TimingResult r;
r = stopWatch.mark("before loop 1");
System.out.println(r);
for (int i=0; i<100; i++) {
slowThing();
}
r = stopWatch.mark("after loop 1");
System.out.println(r);
for (int i=0; i<100; i++) {
reallySlowThing();
}
r = stopWatch.mark("after loop 2");
System.out.println(r);
This gives the nice result of;
First mark: [before loop 1] at time 1436537674704
Mark: [after loop 1] 1037ms since mark [before loop 1]
Mark: [after loop 2] 2008ms since mark [after loop 1]