Measuring Elapsed Time in Java

🕒 Reading time: 7 minutes


TL;DR

  1. System.currentTimeMillis() — Quick and simple for basic timing (milliseconds)
   long startTime = System.currentTimeMillis();
   //your code goes here
   long endTime = System.currentTimeMillis();
   System.out.println("Elapsed time: " + (endTime - startTime) + " ms");
  1. System.nanoTime() — Higher precision, ideal for short-duration tasks (nanoseconds)
   long startTime = System.nanoTime();
   //your code goes here
   long endTime = System.nanoTime();
   System.out.println("Elapsed time: " + (endTime - startTime) / 1_000_000 + " ms");
  1. Instant and Duration (Java 8+) — Readable and clear timing with object-based API (milliseconds)
   Instant start = Instant.now();
   //your code goes here
   Instant end = Instant.now();
   Duration duration = Duration.between(start, end);
   System.out.println("Elapsed time: " + duration.toMillis() + " ms");

Sample Code to Measure

We’ll measure the time taken by this sample method, sumArray, to sum elements in a large array:

public class TimingExample {
    public static long sumArray(int[] numbers) {
        long sum = 0;
        for (int num : numbers) {
            sum += num;
        }
        return sum;
    }
}

1. Using System.currentTimeMillis()

This basic method returns the current time in milliseconds since the Unix epoch. Simple but limited.

long startTime = System.currentTimeMillis();
TimingExample.sumArray(new int[1000000]);
long endTime = System.currentTimeMillis();
System.out.println("Elapsed time: " + (endTime - startTime) + " ms");

When to Use It

  • Quick checks for longer-running processes
  • Useful for basic timing in non-critical areas

When Not to Use It

  • Avoid for short-duration or high-precision needs
  • Susceptible to system clock adjustments

Complexity: Low


2. Using System.nanoTime()

With nanosecond precision, System.nanoTime() is ideal for timing intervals accurately, unaffected by system time changes.

long startTime = System.nanoTime();
TimingExample.sumArray(new int[1000000]);
long endTime = System.nanoTime();
System.out.println("Elapsed time: " + (endTime - startTime) / 1_000_000 + " ms");

When to Use It

  • High-precision timing for short-duration events
  • Reliable for benchmarking intervals

When Not to Use It

  • Avoid for real-world time (clock time)
  • Slight hardware dependence may cause variation

Complexity: Low


3. Instant and Duration (Java 8+)

The Instant and Duration classes offer readable, object-based timing methods.

Instant start = Instant.now();
TimingExample.sumArray(new int[1000000]);
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println("Elapsed time: " + duration.toMillis() + " ms");

When to Use It

  • Ideal for Java 8+ projects focusing on readability
  • Great for general-purpose timing needs

When Not to Use It

  • Avoid if very high precision is critical
  • Minor performance overhead due to object creation

Complexity: Medium


4. Timing with Stopwatch from Guava

Guava’s Stopwatch provides a structured way to time multiple code blocks.

Dependency:

<!-- Maven -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

<!-- Gradle -->
implementation 'com.google.guava:guava:31.0.1-jre'
import com.google.common.base.Stopwatch;

Stopwatch stopwatch = Stopwatch.createStarted();
TimingExample.sumArray(new int[1000000]);
stopwatch.stop();
System.out.println("Elapsed time: " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms");

When to Use It

  • Suitable for projects that already use Guava
  • Allows multiple timing intervals easily

When Not to Use It

  • Avoid if Guava isn’t already in your project
  • Adds unnecessary complexity for simple timing needs

Complexity: Medium


5. Precision Benchmarking with JMH

For advanced benchmarking, JMH (Java Microbenchmark Harness) minimizes JVM-related timing distortions.

Dependency:

<!-- Maven -->
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.36</version>
</dependency>

<!-- Gradle -->
implementation 'org.openjdk.jmh:jmh-core:1.36'

Setting Up the Benchmark

To benchmark sumArray, set up a JMH test class as follows:

import org.openjdk.jmh.annotations.*;

@State(Scope.Thread)
public class MyBenchmark {

    private int[] numbers;

    @Setup
    public void setUp() {
        numbers = new int[1000000];
    }

    @Benchmark
    @Warmup(iterations = 5, time = 1) // 5 warm-up iterations
    @Measurement(iterations = 10, time = 1) // 10 measured iterations
    @Fork(1) // Run in one JVM fork
    @BenchmarkMode(Mode.AverageTime) // Average time per operation
    public long benchmarkSumArray() {
        return TimingExample.sumArray(numbers);
    }
}

Breakdown of Benchmark Setup

  • Warm-up: Stabilizes JIT optimizations.
  • Measurement: Sets up the actual benchmarking phase.
  • Fork: Isolates tests in a separate JVM.
  • BenchmarkMode: Measures average execution time per method call.

Example Output

After running the benchmark, the output might look like this:

Benchmark              Mode  Cnt    Score   Error  Units
MyBenchmark.benchmarkSumArray  avgt   10      0.123 ± 0.005  ms/op

Complexity: High
I’ll write a separate article to cover JMH in more detail, including advanced configurations and benchmarking best practices.


Choosing the Right Tool

Use CaseBest ToolPrecisionComplexity
Quick, informal timingSystem.currentTimeMillis()MillisecondsLow
Short-duration eventsSystem.nanoTime()NanosecondsLow
Readable timing for Java 8+ projectsInstant and DurationMillisecondsMedium
Multiple, structured timing needsStopwatch (Guava)MillisecondsMedium
High-precision benchmarkingJMHNanosecondsHigh

Final Thoughts

Your choice of timing tool depends on your specific needs. currentTimeMillis() and nanoTime() work well for quick checks, while Instant and Duration add readability. For advanced benchmarking, JMH is the industry standard.

Timing isn’t just about measuring milliseconds; it’s about creating a responsive and optimized application. Happy coding!