io.activej.common.time.Stopwatch Maven / Gradle / Ivy
/*
* Copyright (C) 2020 ActiveJ LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.activej.common.time;
import java.util.concurrent.TimeUnit;
import static io.activej.common.Checks.checkState;
import static java.util.concurrent.TimeUnit.*;
public final class Stopwatch {
private boolean isRunning;
private long start;
private long nanos;
private Stopwatch() {}
public static Stopwatch createUnstarted() { return new Stopwatch(); }
public static Stopwatch createStarted() {return new Stopwatch().start(); }
public Stopwatch start() {
checkState(!isRunning, "This stopwatch is already running.");
isRunning = true;
start = System.nanoTime();
return this;
}
public Stopwatch stop() {
long tick = System.nanoTime();
checkState(isRunning, "This stopwatch is already stopped.");
isRunning = false;
nanos += tick - start;
return this;
}
public Stopwatch reset() {
isRunning = false;
nanos = 0;
return this;
}
private long time() {
if (isRunning) {
return System.nanoTime() - start + nanos;
} else {
return nanos;
}
}
private long elapsedNanos() {
return isRunning ? System.nanoTime() - start + nanos : nanos;
}
@Override
public String toString() {
long nanos = elapsedNanos();
TimeUnit unit = chooseUnit(nanos);
double value = (double) nanos / NANOSECONDS.convert(1, unit);
return String.format("%.4g %s", value, abbreviate(unit));
}
public long elapsed(TimeUnit timeUnit) {
return timeUnit.convert(time(), TimeUnit.NANOSECONDS);
}
private static TimeUnit chooseUnit(long nanos) {
if (DAYS.convert(nanos, NANOSECONDS) > 0) {
return DAYS;
}
if (HOURS.convert(nanos, NANOSECONDS) > 0) {
return HOURS;
}
if (MINUTES.convert(nanos, NANOSECONDS) > 0) {
return MINUTES;
}
if (SECONDS.convert(nanos, NANOSECONDS) > 0) {
return SECONDS;
}
if (MILLISECONDS.convert(nanos, NANOSECONDS) > 0) {
return MILLISECONDS;
}
if (MICROSECONDS.convert(nanos, NANOSECONDS) > 0) {
return MICROSECONDS;
}
return NANOSECONDS;
}
private static String abbreviate(TimeUnit unit) {
switch (unit) {
case NANOSECONDS:
return "ns";
case MICROSECONDS:
return "μs";
case MILLISECONDS:
return "ms";
case SECONDS:
return "s";
case MINUTES:
return "min";
case HOURS:
return "h";
case DAYS:
return "d";
default:
throw new AssertionError();
}
}
}