It is a common question: how to measure time lapses in Java, considering the many different hardware platforms out there – different OSs, CPU vendors, number of cores, and so forth.

One other thing to bare in mind: high frequency systems operate in the range of nanoseconds (rarely the case for Java, but nevertheless)

The first option:  System.currentTimeMillis(). A bit of advice: first, read the javadoc (for 1.5):

Returns the current time in milliseconds. Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.

Yes, that’s right: The JVM can be only as accurate as the underlying OS  (and CPU) allows it to be. Some CPUs will report time in millisecond x 10^1, while we are measuring millisecond x 10^(-6).  In an accuracy margin of about 10^3, it hints to the level of errors you might collect.

The second option: System.nanoTime(), again, our old friend – written documentation:

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values may be negative). This method provides nanosecond precision, but not necessarily nanosecond accuracy. No guarantees are made about how frequently values change.

Well, how bad is that? In multi-core machines you can get results indicating that some particles are able to jump back in time, yes. But don’t worry, no quantum physics here. Just small quirks (or justifiable trade-offs?) in the way modern processors are hardware architectures are designed. For Intel processors, for example, check out the RDTSC instruction – reading the 64-bit real-time internal clock (warning: not for the faint of heart).

In a nutshell: Intel designers had the choice between accurate time measurements or speed. Guess which one they picked? — Consequences? Specially for multi-core machines, subsequent reads might result on lower (or equal) timestamps.

Quick note: I kept some other alternatives out – available in the language but notoriously flawed – like Date()

Now the final question: how should we do it? in a few steps:

  • Find out exactly which macro functions you are trying to measure – yes, all will add up to macro functions.
  • Define your benchmark plan around these macro functions
  • Isolate your test subjects into something you can control (dedicated hardware, network, storage)
  • Make sure your test cases execute these macro functions many times, in bulk – simple math, you can get your desired wall-clock given the overall time and the executions
  • Compile the data – parse results, plot cute charts, the works.

That’s it, hope this helps.