This is an automated email from the ASF dual-hosted git repository. reschke pushed a commit to branch OAK-11620 in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit f66d62a5855e53bc5c40dead16f18026c43d74a3 Author: Julian Reschke <[email protected]> AuthorDate: Wed Apr 9 12:14:50 2025 +0100 OAK-11260: Create replacement for Guava Stopwatch --- oak-commons/pom.xml | 3 +- .../jackrabbit/oak/commons/time/Stopwatch.java | 157 +++++++++++++++++++++ .../jackrabbit/oak/commons/time/package-info.java | 28 ++++ .../commons/{StopWatch.java => TestStopWatch.java} | 2 +- .../oak/commons/json/JsopStreamTest.java | 4 +- .../jackrabbit/oak/commons/json/JsopTest.java | 4 +- 6 files changed, 192 insertions(+), 6 deletions(-) diff --git a/oak-commons/pom.xml b/oak-commons/pom.xml index 3b7af3a58d..0f9c378232 100644 --- a/oak-commons/pom.xml +++ b/oak-commons/pom.xml @@ -57,7 +57,8 @@ org.apache.jackrabbit.oak.commons.sort, org.apache.jackrabbit.oak.commons.properties, org.apache.jackrabbit.oak.commons.jdkcompat, - org.apache.jackrabbit.oak.commons.pio + org.apache.jackrabbit.oak.commons.pio, + org.apache.jackrabbit.oak.commons.time </Export-Package> </instructions> </configuration> diff --git a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/time/Stopwatch.java b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/time/Stopwatch.java new file mode 100644 index 0000000000..bbe8153ce1 --- /dev/null +++ b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/time/Stopwatch.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.jackrabbit.oak.commons.time; + +import org.apache.jackrabbit.oak.commons.conditions.Validate; + +import java.time.Clock; +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +/** + * A stop watch based either on a {@link Supplier} of nanoseconds, or a {@link java.time.Clock}. + * <p> + * The accuracy of measurements depends on the precision of the time source, which likely depends on platform and + * configuration. + * <p> + * Inspired by Guava's. + */ +public class Stopwatch { + + private long startTime; + private long accumulated; + private boolean running; + private final Supplier<Long> ticker; + + private Stopwatch(Supplier<Long> ticker) { + this.ticker = ticker; + this.accumulated = 0L; + this.startTime = ticker.get(); + this.running = false; + } + + /** + * @return a running stop watch, using {@link System#nanoTime()}. + */ + public static Stopwatch createStarted() { + return new Stopwatch(Stopwatch::tick).start(); + } + + /** + * @return a running stop watch, using the supplied provider. + */ + public static Stopwatch createStarted(Supplier<Long> ticker) { + return new Stopwatch(ticker).start(); + } + + /** + * @return a running stop watch, using the supplied clock. + * <p> + * Note that only {@link Clock#millis()} will be used, thus the watch will have ms precision at most. + */ + public static Stopwatch createStarted(java.time.Clock clock) { + return new Stopwatch(clockAsLongSupplier(clock)).start(); + } + + /** + * @return a non-running stop watch, using {@link System#nanoTime()}. + */ + public static Stopwatch createUnstarted() { + return new Stopwatch(Stopwatch::tick); + } + + /** + * Starts the stop watch, will fail when running. + * @return the stop watch + */ + public Stopwatch start() { + Validate.checkState(!this.running, "Stopwatch already running."); + this.startTime = this.ticker.get(); + this.running = true; + return this; + } + + /** + * Stops the stop watch, will fail when not running. + * @return the stop watch + */ + public Stopwatch stop() { + Validate.checkState(this.running, "Stopwatch not running."); + this.accumulated += elapsedNanos(); + this.startTime = 0L; + this.running = false; + return this; + } + + /** + * Resets the stop watch, and puts it into stopped state. + * @return the stop watch + */ + public Stopwatch reset() { + this.accumulated = 0L; + this.startTime = 0; + this.running = false; + return this; + } + + /** + * @return whether the stop watch is running + */ + public boolean isRunning() { + return this.running; + } + + /** + * Gets elapsed time using the supplied {@link TimeUnit}. + * @param timeunit time unit + * @return elapsed time in the specified unit + */ + public long elapsed(TimeUnit timeunit) { + return timeunit.convert(elapsedNanos(), TimeUnit.NANOSECONDS); + } + + /** + * Gets elapsed time as {@link Duration}. + * @return elapsed time + */ + public Duration elapsed() { + return Duration.ofMillis(elapsedNanos()); + } + + @Override + public String toString() { + return java.time.Duration.ofNanos(elapsedNanos()).toString(); + } + + // private parts + + private long elapsedNanos() { + long delta = this.running ? this.ticker.get() - this.startTime : 0; + return this.accumulated + delta; + } + + private static long tick() { + return System.nanoTime(); + } + + private static Supplier<Long> clockAsLongSupplier(Clock clock) { + return () -> TimeUnit.MILLISECONDS.toNanos(clock.millis()); + } +} diff --git a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/time/package-info.java b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/time/package-info.java new file mode 100644 index 0000000000..3e9fa9b326 --- /dev/null +++ b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/time/package-info.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * Internal ("private") utilities related to timing... + */ +@Internal(since = "1.0.0") +@Version("1.0.0") +package org.apache.jackrabbit.oak.commons.time; +import org.apache.jackrabbit.oak.commons.annotations.Internal; +import org.osgi.annotation.versioning.Version; + diff --git a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/StopWatch.java b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/TestStopWatch.java similarity index 98% rename from oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/StopWatch.java rename to oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/TestStopWatch.java index 7677b33c56..ed64cdf6f9 100644 --- a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/StopWatch.java +++ b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/TestStopWatch.java @@ -19,7 +19,7 @@ package org.apache.jackrabbit.oak.commons; /** * A utility class to time an operation. */ -public class StopWatch { +public class TestStopWatch { private static final long NANOS_PER_SECOND = 1000 * 1000 * 1000; diff --git a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/json/JsopStreamTest.java b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/json/JsopStreamTest.java index 622a6c112b..2437decdda 100644 --- a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/json/JsopStreamTest.java +++ b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/json/JsopStreamTest.java @@ -17,7 +17,7 @@ package org.apache.jackrabbit.oak.commons.json; import junit.framework.TestCase; -import org.apache.jackrabbit.oak.commons.StopWatch; +import org.apache.jackrabbit.oak.commons.TestStopWatch; public class JsopStreamTest extends TestCase { @@ -25,7 +25,7 @@ public class JsopStreamTest extends TestCase { public static void main(String... args) { for (int k = 0; k < 5; k++) { String s = "Hello \"World\" Hello \"World\" Hello \"World\" Hello \"World\" Hello \"World\" Hello \"World\" "; - StopWatch timer = new StopWatch(); + TestStopWatch timer = new TestStopWatch(); JsopWriter w = k % 2 == 1 ? new JsopBuilder() : new JsopStream(); for (int i = 0; i < 1000000; i++) { w.value(s); diff --git a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/json/JsopTest.java b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/json/JsopTest.java index 93e4e2f197..58cc316749 100644 --- a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/json/JsopTest.java +++ b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/json/JsopTest.java @@ -17,7 +17,7 @@ package org.apache.jackrabbit.oak.commons.json; import junit.framework.TestCase; -import org.apache.jackrabbit.oak.commons.StopWatch; +import org.apache.jackrabbit.oak.commons.TestStopWatch; /** * Test the Jsop tokenizer and builder. @@ -29,7 +29,7 @@ public class JsopTest extends TestCase { for (int k = 0; k < 5; k++) { // String s = "Hello World Hello World Hello World Hello World Hello World Hello World "; String s = "Hello \"World\" Hello \"World\" Hello \"World\" Hello \"World\" Hello \"World\" Hello \"World\" "; - StopWatch timer = new StopWatch(); + TestStopWatch timer = new TestStopWatch(); int t2 = 0; for (int i = 0; i < 1000000; i++) { t2 += JsopBuilder.encode(s).length();
