How can I measure time with microsecond precision in Java?

前端 未结 12 855
死守一世寂寞
死守一世寂寞 2020-12-03 01:15

I saw on the Internet that I was supposed to use System.nanoTime() but that doesn\'t work for me - it gives me the time with milliseconds precision. I just need

相关标签:
12条回答
  • 2020-12-03 01:49

    My guess is that since System.nanoTime() uses the "most precise available system timer" which apparently only has millisecond-precision on your system, you can't get anything better.

    0 讨论(0)
  • 2020-12-03 01:49

    Yes, the accuracy and precision of System.nanoTime is usually much better than System.currentTimeMillis, but without guarantee: it can become just as bad in the worst case.

    ThreadMXBean.getCurrentThreadCpuTime tends to yield smaller times, but its resolution is unclear, and it has further disadvantages (do you really want the CPU time?, platform dependent semantics, supported on your platform?).

    Measuring the time with all three techniques also has some cost, i.e. requires time itself, which can distort the measurements. The costs are highly platform dependent, but often cost(System.currentTimeMillis) << cost(System.nanoTime) << cost(ThreadMXBean.getCurrentThreadCpuTime).

    About micro benchmarking in general, see

    • How do I write a correct micro-benchmark in Java?
    • Create quick/reliable benchmark with java?
    0 讨论(0)
  • 2020-12-03 01:53

    Using java.time

    FYI, Java 9 and later has a fresh implementation of Clock that can capture the current moment in up to nanoseconds resolution.

    The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

    Call Instant.now to capture the current moment.

    • In Java 9 and later, you get a resolution up to nanoseconds for that current moment.
    • In Java 8, the current moment is captured only up to milliseconds resolution (you can indeed hold values with nanoseconds, but only capture current moment in milliseconds).

      Instant instant = Instant.now() ;

    Represent a span of time unattached to the timeline with Duration class. Holds an amount of time in terms of seconds and nanoseconds.

    Duration d = Duration.between( instantThen , Instant.now() );
    

    To be clear, the microseconds resolution asked in the Question is in between the granularities of milliseconds and nanoseconds. Number of places in a decimal fraction: millis is 3 (0.123), micros is 6 (0.123456), nanos is 9 (0.123456789).

    Caveat

    Java relies on your computer’s hardware clock. As others warned, that hardware will almost certainly capture time with far less accuracy and far less resolution than nanoseconds.

    Benchmarking at such fine granularity is fraught with issues and not advisable generally.

    And beware of premature optimization.

    There is a proposal to add micro-benchmarking facility to the Java platform in JEP 230: Microbenchmark Suite. Based on the Java Microbenchmark Harness (JMH).


    About java.time

    The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

    The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

    To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

    Where to obtain the java.time classes?

    • Java SE 8 and SE 9 and later
      • Built-in.
      • Part of the standard Java API with a bundled implementation.
      • Java 9 adds some minor features and fixes.
    • Java SE 6 and SE 7
      • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
    • Android
      • The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
      • See How to use ThreeTenABP….

    The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

    0 讨论(0)
  • 2020-12-03 01:55

    That's weird. System.nanoTime() is supposed to work. Are you using the Sun JVM?

    Can you just repeat your operation 1000 times and divide the time by 1000 to find out what you need to know?

    0 讨论(0)
  • 2020-12-03 01:56

    a "quick and dirty" solution that I eventually went with:

    TimeUnit.NANOSECONDS.toMicros(System.nanoTime());
    

    UPDATE:

    I originally went with System.nanoTime but then I found out it should only be used for elapsed time, I eventually changed my code to work with milliseconds or at some places use:

    TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
    

    but this will just add zeros at the end of the value (micros = millis * 1000)

    Left this answer here as a "warning sign" in case someone else thinks of nanoTime :)

    0 讨论(0)
  • 2020-12-03 01:58

    You have to repeat the tests thousands of times. There are lots of things happening that will influence your measurements, like garbage collection, I/O, swap in/out, the size of the ready-queue threads, etc.

    0 讨论(0)
提交回复
热议问题