/**
*
* Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved.
*
* 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 com.speedment.common.benchmark.internal;
import com.speedment.common.benchmark.Stopwatch;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.*;
/**
*
* @author pemi
*/
public final class StopwatchImpl implements Stopwatch {
private long start;
private long stop;
public StopwatchImpl() {
reset();
}
@Override
public long elapsed(TimeUnit timeUnit) {
return timeUnit.convert(elapsedNanos(), NANOSECONDS);
}
@Override
public long elapsedMillis() {
return elapsedNanos() / 1_000_000L;
}
@Override
public long elapsedNanos() {
final long now = System.nanoTime();
final long elapsedNano;
if (isStopped()) {
elapsedNano = stop - start;
} else {
elapsedNano = now - start;
}
return elapsedNano;
}
@Override
public boolean isStarted() {
return start > 0;
}
@Override
public boolean isStopped() {
return stop > 0;
}
@Override
public Stopwatch start() {
if (isStarted()) {
throw new IllegalStateException(Stopwatch.class.getName() + " already started.");
}
start = System.nanoTime();
return this;
}
@Override
public Stopwatch stop() {
long now = System.nanoTime();
if (isStopped()) {
throw new IllegalStateException(Stopwatch.class.getName() + " already stopped.");
}
if (!isStarted()) {
throw new IllegalStateException(Stopwatch.class.getName() + " not started.");
}
stop = now;
return this;
}
@Override
public Stopwatch reset() {
start = -1;
stop = -1;
return this;
}
@Override
public String toString() {
final long nanos = elapsedNanos();
final TimeUnit unit = timeUnitFor(nanos);
final double value = (double) nanos / NANOSECONDS.convert(1, unit);
return String.format("%,.2f %s", value, unitShortText(unit));
}
private static TimeUnit timeUnitFor(long nanos) {
if (SECONDS.convert(nanos, NANOSECONDS) > 1) {
return SECONDS;
}
if (MILLISECONDS.convert(nanos, NANOSECONDS) > 1) {
return MILLISECONDS;
}
if (MICROSECONDS.convert(nanos, NANOSECONDS) > 1) {
return MICROSECONDS;
}
return NANOSECONDS;
}
private static String unitShortText(TimeUnit unit) {
switch (unit) {
case SECONDS:
return "s";
case MILLISECONDS:
return "ms";
case MICROSECONDS:
return "us";
case NANOSECONDS:
return "ns";
default:
throw new AssertionError();
}
}
}