StopWatch
About
The StopWatch class in Apache Commons Lang (org.apache.commons.lang3.time.StopWatch) is a utility designed to measure elapsed time in a precise and convenient manner. It is particularly useful in scenarios such as performance testing, benchmarking, profiling sections of code, or monitoring the execution duration of critical operations. Unlike manually recording system timestamps (System.currentTimeMillis() or System.nanoTime()), StopWatch abstracts away the boilerplate code and provides a clean API for starting, stopping, suspending, resuming, and querying elapsed times.
Features
Start/Stop Timing
We can start the stopwatch at a given point in our code and stop it after execution.
The elapsed time between these points is recorded.
Suspend/Resume Support
The stopwatch can be temporarily suspended and later resumed.
This is useful when we want to exclude certain operations from timing.
Split and Unsplit
Allows capturing an intermediate time (split) without stopping the stopwatch.
Splits are useful when monitoring progress in long-running tasks.
Multiple Time Units
Elapsed time can be retrieved in various units: nanoseconds, milliseconds, seconds, minutes, hours, or days.
This provides flexibility for both fine-grained benchmarking and high-level reporting.
Thread Safety
The basic
StopWatchimplementation is not thread-safe.For concurrent environments, external synchronization or per-thread instances should be used.
Readable Formatting
Supports string formatting of elapsed time in a human-readable style (e.g.,
00:01:23.456).Useful for logging and reporting.
Method Reference
Method
Action / Meaning
Constructor
StopWatch()
Creates a new stopwatch (initial state: unstarted).
Core Controls
start()
Starts the stopwatch. Throws IllegalStateException if already started.
stop()
Stops the stopwatch. No more time accumulates until reset.
reset()
Resets stopwatch to the unstarted state (time = 0). Must be called before reusing.
split()
Records the current elapsed time as a split point (does not stop the watch).
unsplit()
Clears the last split. Needed before making another split.
suspend()
Pauses the stopwatch (time is frozen).
resume()
Resumes from a suspended state.
Time Retrieval
getTime()
Returns total elapsed time (in milliseconds) between start and now (or stop).
getNanoTime()
Returns total elapsed time (in nanoseconds) for higher precision.
getSplitTime()
Returns elapsed time (in ms) at the point of the last split.
getSplitNanoTime()
Returns elapsed time (in ns) at the last split.
String Output
toString()
Returns formatted elapsed time as HH:mm:ss.SSS (human-readable).
toSplitString()
Returns formatted split time as HH:mm:ss.SSS.
State Inspection
isStarted()
Returns true if stopwatch has been started.
isStopped()
Returns true if stopwatch has been stopped.
isSuspended()
Returns true if stopwatch is currently suspended.
isStarted()
Returns true if stopwatch has been started (but not necessarily running).
Static Factory (Commons Lang 3.6+)
StopWatch.createStarted()
Creates and starts a new stopwatch in one call.
StopWatch.create()
Creates a new stopwatch in the unstarted state.
Use Cases
Performance Testing – Measure the execution time of a method or algorithm to identify bottlenecks.
Benchmarking – Compare the performance of multiple implementations of the same logic.
Profiling – Track elapsed times for different stages of a workflow using splits.
Monitoring – Record execution times for API calls, database queries, or batch processes.
Operational Logging – Add duration details in logs for observability and debugging.
Usage Examples
1. Basic Start and Stop
The simplest use case is measuring elapsed time for a block of code.
2. Restart for Multiple Measurements
If we want to reuse the same stopwatch for different measurements, use reset() and start() again.
3. Split and Unsplit (Intermediate Checkpoints)
Splits let us measure checkpoints without stopping the stopwatch.
4. Suspend and Resume
When certain parts of code shouldn’t be included in measurement, use suspend/resume.
Output: Approximately 2000 ms (1 sec before + 1 sec after, 2 sec suspended excluded).
5. Measuring in Different Time Units
StopWatch provides elapsed time in multiple units.
6. Logging with Human Readable Format
The stopwatch can output a nicely formatted string (HH:mm:ss.SSS).
7. Benchmarking Multiple Algorithms
We can measure and compare performance of different implementations.
8. Profiling Stages in a Workflow
Using splits for stage-wise profiling.
9. Integrating with Logging Framework
Often used with SLF4J for structured logs.
Best Practices
1. Always Stop Before Reuse
Best Practice: A
StopWatchmust be stopped before callingreset()or starting again.Pitfall: Forgetting to stop and directly calling
start()will throw anIllegalStateException.
2. Use Reset for Multiple Measurements
Best Practice: Call
reset()before starting a new measurement cycle.Pitfall: Without reset, elapsed times accumulate across runs, leading to misleading results.
3. Use Suspend/Resume Carefully
Best Practice: Suspend timing when executing operations that should not count (like sleeping, waiting for external systems).
Pitfall: Forgetting to call
resume()will lead to under-reporting elapsed time.
4. Prefer toString() for Logging
toString() for LoggingBest Practice: Use
toString()for human-readable log output (HH:mm:ss.SSS).Pitfall: Printing
getTime()(ms only) is less meaningful for long-running tasks.
5. Benchmark with Warmup
Best Practice: For performance benchmarking (e.g., comparing algorithms), always do a warm-up run (JVM JIT optimization may skew first measurements).
Pitfall: Running StopWatch only once and assuming results are representative of real performance.
6. Avoid Multi-Threaded Sharing
Best Practice: Each thread should have its own
StopWatchinstance.Pitfall: Sharing a single
StopWatchacross threads is not thread-safe and leads to corrupted timings.
7. Measure Specific Sections with Splits
Best Practice: Use
split()to capture intermediate milestones without stopping the clock.Pitfall: Forgetting to call
unsplit()before using some operations (like another split) may throw exceptions.
8. Choose the Right Time Unit
Best Practice: Use
getNanoTime()for precise measurement (e.g., micro-benchmarking).Pitfall: Using only
getTime()(ms precision) may lose accuracy in very fast-running tasks.
9. Do Not Mix StopWatch with System.currentTimeMillis()
Best Practice: Stick to one timing approach (StopWatch provides consistent, encapsulated API).
Pitfall: Mixing with manual timestamp differences may lead to confusion.
10. Clean Logging
Best Practice: Wrap StopWatch usage inside try/finally for guaranteed stop and log output.
Pitfall: Forgetting to stop a stopwatch in case of exceptions can leave it in an invalid state.
Last updated