Performance monitoring precision

Monitoring application performance is a primary use case of commons-monitoring. Java provides 2 timers implementation, as System.currentTimeMillis and System.nanoTime().

Those timers methods performances and real precision depends on the hardware, OS and JRE implementation.

MS Windows

Based on SUN technical documentation, both implementation precision depend on underlying hardware.

  • currentTimeMillis uses a native windows low resolution timer, and for this reason is VERY quick (6 cycles), with a precision of only 10 to 15ms. Using this method as lower impacts on the application, but monitoring a process taking less than 15ms may produce elapsedTime=0 !
  • nanoTime uses Windows Performance API (when available) that is both hardware and version (and service pack) dependent (user timers, ACPI timers or CPU-level timers...). In most cases, this requires slow I/O instruction and result in microsecond accuracy. In better case requesting an on-chip timer requires ~100 cycles.

Both SUN JRE and Bea Jrockit implementation shows bad performances of nanoTime on Windows, but the currentTimeMillis precision is too limited for use as fine-grained performance counters.

Sun Solaris

On this platform, a quick & dirty bench [1] demonstrates both methods have comparable performances. No technical info on real precision, but nanoTime would give the better one available.

Other systems

?? any info available ??

Java 1.3 / Java 1.4

backport-util-concurrent (used to backport commons-monitoring on pre-java5) provides an implementation of System.nanoTime that delegates to currentTimeMillis with unit conversion. On Sun JRE 1.4 it also uses an internal SUN performance package to get a better precision.

conclusion

Based on those informations, currentTimeMillis - even with nice performances on Windows - cannot be used for fine-grained monitoring. In all cases nanoTime provides the better time-counter available on the system, in terms of both precision and fiability

[2]

public class CurrentTimeMillisVsNanoTime
{
    static int loops = 1000000;
    public static void main( String[] args )
    {
        long time = System.nanoTime();
        for ( int i = 0; i < loops; i++ )
        {
            System.nanoTime();
        }
        System.out.println( "System.nanoTime took     : " + (System.nanoTime() - time) + "ns" );

        time = System.nanoTime();
        for ( int i = 0; i < loops; i++ )
        {
            System.currentTimeMillis();
        }
        System.out.println( "System.currentTimeMillis : " + (System.nanoTime() - time) + "ns" );
    }
}
  • No labels