How do I time a method's execution in Java?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
If you want a quick, practical timing in Java, use System.nanoTime(). If you want trustworthy benchmark numbers for very fast methods, use JMH instead, because naive timing is easily distorted by JIT warmup, dead-code elimination, and JVM optimizations.
The Simple Timing Pattern
For ordinary profiling during development, wrap the method call with System.nanoTime().
System.nanoTime() is preferred over System.currentTimeMillis() for elapsed-time measurement because it is designed for monotonic interval timing rather than wall-clock time.
A Reusable Helper
If you need this often, wrap the pattern in a helper method.
That is enough for logging, smoke-checking performance regressions, or comparing slower application operations.
Why Naive Microbenchmarks Lie
Very short methods are hard to measure correctly on the JVM. The runtime may optimize away work, inline methods, or change performance after warmup.
That means code like this is often misleading:
- run the method once
- print one timing number
- assume the number is stable
For quick diagnostics, repeat the method many times and warm up first. For serious measurement, use JMH.
When to Use JMH
JMH exists specifically to benchmark JVM code correctly. It handles warmup iterations, measurement iterations, forks, and several optimization pitfalls that manual timing does not.
A minimal benchmark looks like this:
That example is not a full JMH project setup, but it shows the intended direction: once timing results matter, move from ad hoc code to a benchmarking framework.
Another practical distinction is whether you are measuring one slow operation or a tiny hot method. For code that already takes milliseconds or seconds, a simple nanoTime() wrapper is often enough. For code that runs in microseconds or nanoseconds, framework-based benchmarking becomes much more important.
Timing in Production Code
For production systems, manual timers are rarely the best observability tool. Use metrics libraries, tracing, or APM tooling instead. They provide percentiles, aggregation, and context that a single log line cannot.
So there are really three levels:
- '
System.nanoTime()for quick local timing' - JMH for repeatable benchmarks
- metrics or tracing for live systems
Common Pitfalls
The biggest mistake is using System.currentTimeMillis() for tiny operations. Its granularity and wall-clock nature make it a worse fit for elapsed timing.
Another mistake is benchmarking code that the JVM can optimize away. If the result is unused, the measurement may not reflect real work.
A third mistake is timing only one run and treating it as stable. JVM warmup changes performance significantly.
Summary
- Use
System.nanoTime()for quick method timing in Java. - Wrap the timing pattern in a helper if you do it often.
- Avoid
System.currentTimeMillis()for short elapsed-time measurements. - For microbenchmarks, use JMH instead of hand-rolled loops.
- For production visibility, prefer metrics and tracing over ad hoc timing prints.
Related reading
- How do I trim whitespace?
- How do I trim whitespace?
- How do I trim whitespace from a string?
- How do I type hint a method with the type of the enclosing class?
- How do I trim a file extension from a String in Java?
- How do I turn a String into a InputStreamReader in java?
- How do I use a dump file to diagnose a memory leak?
- How do I use TTL on clickhouse table?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.