method execution time
performance measurement
logging execution time
millisecond precision
code optimization

How to log a method's execution time exactly in milliseconds?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

You cannot log a method's execution time exactly in milliseconds in the strict mathematical sense. Operating-system scheduling, clock resolution, garbage collection, and measurement overhead all introduce noise, so the real goal is to measure elapsed time accurately enough for engineering decisions.

Use a Monotonic Clock, Not Wall Time

For duration measurement, use a monotonic timer. Wall-clock APIs such as currentTimeMillis can jump due to clock synchronization and are better suited for timestamps than elapsed-time measurement.

In Java, System.nanoTime() is the standard choice for timing code execution.

java
1import java.util.function.Supplier;
2
3public final class Timing {
4    public static <T> T measure(String label, Supplier<T> action) {
5        long start = System.nanoTime();
6        try {
7            return action.get();
8        } finally {
9            long elapsedNanos = System.nanoTime() - start;
10            double elapsedMillis = elapsedNanos / 1_000_000.0;
11            System.out.printf("%s took %.3f ms%n", label, elapsedMillis);
12        }
13    }
14
15    public static void main(String[] args) {
16        String value = measure("sort", () -> {
17            try {
18                Thread.sleep(25);
19            } catch (InterruptedException e) {
20                Thread.currentThread().interrupt();
21            }
22            return "done";
23        });
24
25        System.out.println(value);
26    }
27}

This gives you millisecond output while still measuring with nanosecond-resolution hardware when available.

Why "Exactly" Is the Wrong Requirement

Even with a high-resolution timer, the measured value includes more than your method body. It includes timer-call overhead, thread scheduling gaps, JIT warmup effects, cache behavior, and sometimes work done by the runtime on behalf of your method.

That does not make the measurement useless. It means the measurement is observational, not perfect. For logging and troubleshooting, that is usually enough. For serious benchmarking, you need repeated runs, warmup, and statistical analysis rather than one log line.

Logging in Milliseconds Versus Measuring in Milliseconds

Measure with the finest practical timer, then format in milliseconds for readability. Logging only integer milliseconds throws away detail and can make fast methods appear to take zero time.

For example, 0.173 ms is much more informative than 0 ms. If your logging policy requires integers, round at the very end rather than measuring with a coarse clock.

It is also useful to log the method label, input size, or request identifier beside the duration. A timing number without context is hard to compare later, especially when the same method runs on very different workloads.

When Logging Is Not Enough

Timing one method call in production logs is good for spotting slow outliers, but it is not a substitute for a profiler. If you are investigating micro-optimizations, benchmark with a proper harness. If you are diagnosing end-user latency, include surrounding context such as input size, request ID, and downstream service timings.

Good measurement depends on asking the right question. A single timing line is excellent for operational visibility and weak for performance science.

Common Pitfalls

  • Using wall-clock time for durations can produce misleading results if the system clock changes.
  • Logging integer milliseconds for very fast methods hides useful sub-millisecond variation.
  • Treating one measurement as exact ignores scheduler noise, JIT warmup, and runtime overhead.
  • Benchmarking by adding log statements inside tight loops changes the thing you are trying to measure.
  • Comparing timings across machines without noting workload and environment usually leads to bad conclusions.

Summary

  • Exact millisecond timing is not realistic, but reliable elapsed-time measurement is.
  • Use a monotonic clock such as System.nanoTime() for durations.
  • Measure with fine resolution and format the result in milliseconds for humans.
  • Add enough context to timing logs so the number can be interpreted later.
  • One log line is useful for diagnostics, but not a substitute for proper benchmarking.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.