|
SystemTimersGranularity
How good are ms/ns timers?
System timers granularityWhen you want to measure elapsed time you have generally two options:
We used other.SystemTimersPrecision class to test how often both timer change. Test configurations was Intel Q6600 Core 2 Quad @2.4GHz, 2GB RAM and we used Windows XP, JDK 1.6.0_05 and Ubuntu Linux 8.04 with 2.6.24 kernel, JDK 1.6.0_06. Windows resultsRound: 5
msChanges: 188 during 2937 ms
deltaCount = {15=71, 16=117}
nsChanges: 10000000 during 2934537656 ns
ns1 = 6363881652561
ns2 = 6363881652813 (diff: 252)
ns2 = 6363881653060 (diff: 247)
ns2 = 6363881653311 (diff: 251)
ns2 = 6363881653559 (diff: 248)As you can see the result returned by currentTimeMillis changed only 188 times during nearly 3 seconds. It changed 71 times by 15 ms and 117 times by 16 ms - that indicates timer precision somewhere between these values. 15.625 ms is reported ms timer frequency on multi-processor HW (or multicore as in my case) while 10 ms are reported on single processor (see the link in the Conclusion). Nanoseconds changed on every call and typical difference between two successive calls was ~250 ns. That is effective overhead of this call on Windows XP. (Updated: See the comments for more results, some of them less satisfying.) Linux resultsRound: 5
msChanges: 3162 during 3162 ms
deltaCount = {1=3162}
nsChanges: 10000000 during 3161736190 ns
ns1 = 6858922149416
ns2 = 6858922149570 (diff: 154)
ns2 = 6858922149720 (diff: 150)
ns2 = 6858922149873 (diff: 153)
ns2 = 6858922150027 (diff: 154)Linux shows perfect ms accuracy while nanoseconds can't be judged because the call itself takes around 150 ns. Millis were not perfect at the start of the application: Round: 1
msChanges: 3174 during 3217 ms
deltaCount = {1=3172, 20=1, 25=1}
nsChanges: 10000000 during 3217662606 nsBut later after some warmup ms timer is really convincing. If there is any other difference than 1 ms I'd probably suspect OS scheduler granularity rather than ms timer itself. ConclusionOn the reference HW Linux has slower millis but the granularity is as good as millis need. Slower call is not really the problem because you can't measure very short durations with millis anyway. Nanosecond timer is slightly faster on Linux than on Windows and its usability is roughly the same on both platforms. The most important thing is that it is viable to measure time spans in nanoseconds - it's even better to do so because current HW is very fast and many spots in your application are often n-times shorter than 1 ms. If you want to learn more about various timers you can use and their reported precision on various platform, check this link: http://www.ibm.com/developerworks/java/library/j-benchmark1.html#table1 |
Windows Vista results
I ran the same tests on Windows Vista, on my laptop (Core2 Duo, 2.2Ghz). The results show that Vista (and hence presumably also Windows Server 2008 and Windows 7) also have perfect ms accuracy:
Round: 5 msChanges: 13234 during 13241 ms deltaCount = {1=13230, 2=2, 3=1, 4=1} nsChanges: 10000000 during 13242330240 ns ns1 = 776776487614696 ns2 = 776776487615954 (diff: 1258) ns2 = 776776487617211 (diff: 1257) ns2 = 776776487618538 (diff: 1327) ns2 = 776776487619795 (diff: 1257)Windows XP SP3 slow results
Eirik, thank you for your results on Vista, it's also good to see the millis precision better there. :-) I don't know what's the problem (SP3? JDK update 11?) but nano timer is extremely slow on Windows for me recently. It's not real show-stopper for JavaSimon??? on Windows, but it's definitely unlucky trouble when someone wants to use Simon to measure heavy computation in a fine-grained manner:
Round: 5 msChanges: 1298 during 20281 ms deltaCount = {15=487, 16=811} nsChanges: 10000000 during 20270539133 ns ns1 = 2003943639205 ns2 = 2003943641161 (diff: 1956) ns2 = 2003943643116 (diff: 1955) ns2 = 2003943645072 (diff: 1956) ns2 = 2003943647307 (diff: 2235)I see that Vista is also slower than my previous measurements, but ~2000 ns is really extreme.
Sparc/Solaris 10, Sun Fire 880; JDK 6, update13
Sparc/Solaris provides quite fast nanotimer, values are always rounded to hundreds.
Round: 5 msChanges: 4210 during 4210 ms deltaCount = {1=4210} nsChanges: 10000000 during 4210901400 ns ns1 = 10112714918016100 ns2 = 10112714918016300 (diff: 200) ns3 = 10112714918016600 (diff: 300) ns4 = 10112714918016800 (diff: 200) ns5 = 10112714918017000 (diff: 200)