<< My role | Home | Interested in software architecture? >>
Twitter RSS feed for Simon Brown [Twitter] simonbrown: Eating cream cakes in the sun at jersey zoo ... chillin'

Coding the Architecture RSS feed for Simon Brown [Coding the Architecture] Just a short note to plug a handful of sessions that Kevin and I are presenting at the upcoming Software Architect 2008 conference, 3rd-5th June, London. 1. Coding the Architecture : From Developer to Architect The first is a re-run of our ...

Millisecond accuracy in Java

It is possible, but not on all platforms

I'm about to start a short consulting engagement where we need to performance test a low latency trading system. By low latency, I mean that messages need to flow through the system in under 50ms.

Performance testing work throws up lots of potential issues such as whether you can get access to accurate timestamps, whether system clocks are synchronised, etc. Another such issue is whether you can measure the time taken to make a request in an accurate way.

Let's say that you want to measure the time taken to make a synchronous request to a remote resource and measure how long that request takes. Additionally, let's say that you want to do this under load, simulating various numbers of concurrent users/sessions. One technical solution to this problem is to use something like JMeter to graph the response times across a varying load. Alternatively, you could write something bespoke. However you do it, you need to be sure that you can measure time as accurately as possible.

If you're writing a test harness in Java, you can use System.currentTimeMillis() or System.nanoTime() (Java 5) to get an accurate measurement of the current time. However, if you're going to do this, it's worth reading the Javadocs for each of these methods because they don't guarantee millisecond accuracy. From System.currentTimeMillis() :

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.

So how accurate is it? On Windows, System.currentTimeMillis() doesn't give you the current time to an exact 1ms resolution because of the way that the Windows system clock works. To demonstrate this, I wrote a simple Java program (download as an executable JAR file) that collects the current time for a short period and then displays a consolidated view of the results. The output below shows the raw time in milliseconds, the human formatted version, the number of times System.currentTimeMills() returned that same time and the delta from the previous time.

raw=1187645263093 | formatted=20-Aug-2007 22:27:43:093 | frequency=107567 | delta=15ms
raw=1187645263109 | formatted=20-Aug-2007 22:27:43:109 | frequency=107808 | delta=16ms
raw=1187645263125 | formatted=20-Aug-2007 22:27:43:125 | frequency=103450 | delta=16ms
raw=1187645263140 | formatted=20-Aug-2007 22:27:43:140 | frequency=231928 | delta=15ms
raw=1187645263156 | formatted=20-Aug-2007 22:27:43:156 | frequency=229545 | delta=16ms

As you can see, Windows tends to provide a clock resolution of about 15ms. I ran this on a couple of reasonably spec'd Windows XP and Windows Server 2003 boxes, and using the Sun and BEA JVMs. However, running the same program on Redhat (2.6.9 kernel) and Mac OS X (10.4.x, PPC G4 and Intel Core Duo) gave the following results.

raw=1187645137371 | formatted=20-Aug-2007 22:25:37:371 | frequency=3302 | delta=1ms
raw=1187645137372 | formatted=20-Aug-2007 22:25:37:372 | frequency=3282 | delta=1ms
raw=1187645137373 | formatted=20-Aug-2007 22:25:37:373 | frequency=3295 | delta=1ms
raw=1187645137374 | formatted=20-Aug-2007 22:25:37:374 | frequency=2272 | delta=1ms
raw=1187645137375 | formatted=20-Aug-2007 22:25:37:375 | frequency=3293 | delta=1ms

These simple tests show that some platforms do provide millisecond accuracy. System.nanoTime() is an alternative but this has it's own *additional* problems - I've found the actual call to be slower and the time returned is relative to a fixed but arbitrary time. My initial reaction was that Java is no good for performance testing, but I take that back and make the following recommendations instead.

  • If you need to measure latencies in a "low latency" system, you need to do this on a platform that has an accurate clock resolution. Check your platform does provide millisecond accuracy before you start testing.
  • Don't try to measure accurate response times/latencies on the Windows platform, unless you've tweaked your OS.
  • Don't use Windows to generate load if part of your test data/request includes a millisecond accurate timestamp that you want to pass around the system.

Basically, don't use Windows. ;-)



Re: Millisecond accuracy in Java

This is an interesting one. We had some fun with Message Broker where timestamps in Java nodes were actually coming out "before" timestamps from ESQL Compute nodes that came sequentially earlier in the flow (on Solaris). In the end, it was resolved by calling the Java timestamp from ESQL so the underlying routines are the same, but I guess the accuracy of Java vs C timestamping differs depending on platform.

Re: Millisecond accuracy in Java

Now that is odd. I thought all calls would have gone through the same OS calls, but perhaps not in this case?

Re: Millisecond accuracy in Java

I don't think there's a problem with measuring timings using System.nanoTime() on Windows. Changing your test to use: System.nanoTime() / 1000000 instead of: System.currentTimeMillis() seems to give a delta of 1ms each time for me (on Windows XP). The "fixed but arbitrary time" thing is only a problem if your measurements are more than 292 years apart (and we're talking low latency here, right?!), or you're passing raw data from one system to another.

Re: Millisecond accuracy in Java

Yes, you're right. I get <1ms timings using System.nanoTime(), but the "arbitrary time" means that I can't pass it across JVM boundaries.

Re: Millisecond accuracy in Java

This is common problem for people trying to develop games with Java. You might search forums in http://www.javagaming.org/

Re: Millisecond accuracy in Java

Its worth pointing out that one of the many improvements made to the 2.6 Linux kernel involved changing the default Hertz from 100Hz to 1000Hz. That's why you will get a delta of 10ms if you are trying to profile java apps with System.currentTimeMillis() on a 2.4 kernel.

What I would be really interested to know is impact of the new tickless kernel that will undoubtedly be making its way to servers.

Re: Millisecond accuracy in Java

Hi Simon, if you need to verify all timeframe and delay why you don't use MQSeries ? Only for testing and measuring. With MQSeries frequently I could reach committed transaction in less the 18-22ms. With the monitor services you could understand where and in which part of transaction you loose time... Frequently I use it only for testing communication issues. Best Regards Renato Gabriele Ucci

Re: Millisecond accuracy in Java

Hi Simon, I forgot a tip, but I'm sure you know that, you can use directly MQSeries commands and API directly with java classes, where you can verify everything, also to use two phase commit of messaging, peaking and monitor the progress of transaction. Also doing commit and rallback after completed transaction between the end-points, Best Reagards Remagio

Re: Millisecond accuracy in Java

Common problem. Let me please add my shameless plug.

This is why i created my own timing lib, based on 1.5 nanotime, and can accurately return time in milliseconds, providing an easy replacement for currentTimeMillis().

https://preciseinternaldate.dev.java.net

It is java1.5, but pure (no external lib, no native), very small and very easy to use.

Re: Millisecond accuracy in Java

Hi, I've run the following small program on Windows Vista: public static void main(String[] args) String s = ""; for (int i = 0; i < 1000; i++) s+= System.currentTimeMillis() +"\n"; System.out.println(s); } ... and got the following output (condensed): 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896340 1203315896341 1203315896341 . . . 1203315896370 1203315896370 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 1203315896371 This indicates that Windows is able to measure time in a resolution of milliseconds (or greater). Does anyone know if time measurement was in fact improved on windows vista? I've also run the same program on Windows 2003 and the time resolution was indeed about 15ms. However, replacing currentTimeMillis() with nanoTime(), I got the following output: 1584701197219 1584701324889 1584701354222 1584701381600 1584701408698 . . . Which also seems to indicate that even Windows 2003 is able to provide accurate time measurements. So, is it possible that the inaccuracy of currentTimeMillis() method on Win XP/2003 has its origins on JVM implementation for these OS?

Re: Millisecond accuracy in Java

I thought that the problems were in the OS, not the JVM implementation per se.

Re: Millisecond accuracy in Java

Hi Simon, this is definitely a kernel configuration issue on Linux (not sure about windows). Most out of the box kernels will resolve to 10ms on Linux, however they can easily be patched to resolve to 1ms. This is definitely not a Java/JVM limitation. http://elinux.org/Kernel_Timer_Systems

Add a comment Send a TrackBack