You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by or...@apache.org on 2022/08/22 13:39:07 UTC

[camel] branch main updated: CAMEL-18417: use a monotonic clock source for the StopWatch

This is an automated email from the ASF dual-hosted git repository.

orpiske pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new c2a96369baa CAMEL-18417: use a monotonic clock source for the StopWatch
c2a96369baa is described below

commit c2a96369baa983884ece9d7a703d393650119998
Author: Otavio Rodolfo Piske <an...@gmail.com>
AuthorDate: Mon Aug 22 13:21:59 2022 +0200

    CAMEL-18417: use a monotonic clock source for the StopWatch
---
 .../management/mbean/ManagedBacklogDebugger.java   |  3 +-
 .../main/java/org/apache/camel/util/StopWatch.java | 36 +++++----
 .../java/org/apache/camel/util/StopWatchTest.java  | 89 ++++++++++++++++++++++
 3 files changed, 113 insertions(+), 15 deletions(-)

diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java
index 0fb57d6fc0b..c1a4a3015ca 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java
@@ -397,7 +397,8 @@ public class ManagedBacklogDebugger implements ManagedBacklogDebuggerMBean {
                                             StringHelper.limitLength(suspendedExchange.getFromEndpoint().getEndpointUri(), 100))
                             + "]";
                 }
-                long elapsed = new StopWatch(suspendedExchange.getCreated()).taken();
+
+                long elapsed = StopWatch.elapsedMillisSince(suspendedExchange.getCreated());
 
                 messageHistoryBuffer
                         .append("    <messageHistoryEntry")
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/StopWatch.java b/core/camel-util/src/main/java/org/apache/camel/util/StopWatch.java
index f2573f640d6..71d6625e31b 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/StopWatch.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/StopWatch.java
@@ -16,7 +16,7 @@
  */
 package org.apache.camel.util;
 
-import java.util.Date;
+import java.time.Duration;
 
 /**
  * A very simple stop watch.
@@ -31,14 +31,7 @@ public final class StopWatch {
      * Starts the stop watch
      */
     public StopWatch() {
-        this.start = System.currentTimeMillis();
-    }
-
-    /**
-     * Starts the stop watch from the given timestamp
-     */
-    public StopWatch(Date startTimestamp) {
-        start = startTimestamp.getTime();
+        this.start = System.nanoTime();
     }
 
     /**
@@ -55,7 +48,7 @@ public final class StopWatch {
      */
     public StopWatch(boolean start) {
         if (start) {
-            this.start = System.currentTimeMillis();
+            this.start = System.nanoTime();
         }
     }
 
@@ -63,7 +56,7 @@ public final class StopWatch {
      * Starts or restarts the stop watch
      */
     public void restart() {
-        start = System.currentTimeMillis();
+        start = System.nanoTime();
     }
 
     /**
@@ -73,10 +66,25 @@ public final class StopWatch {
      */
     public long taken() {
         if (start > 0) {
-            return System.currentTimeMillis() - start;
-        } else {
-            return 0;
+            long delta = System.nanoTime() - start;
+
+            return Duration.ofNanos(delta).toMillis();
         }
+
+        return 0;
+    }
+
+    /**
+     * Utility method to provide the elapsed time using milliseconds since epoch. This serves as an alternative for the
+     * former constructor based on a Date argument. This should be used only when converting old code that relies on
+     * that constructor as it can provide incorrect measurements in rare circumstances
+     * 
+     * @param  start the timestamp in milliseconds since epoch
+     * @return       the elapsed time in milliseconds
+     */
+    @Deprecated
+    public static long elapsedMillisSince(long start) {
+        return Duration.ofMillis(System.currentTimeMillis()).minusMillis(start).toMillis();
     }
 
 }
diff --git a/core/camel-util/src/test/java/org/apache/camel/util/StopWatchTest.java b/core/camel-util/src/test/java/org/apache/camel/util/StopWatchTest.java
new file mode 100644
index 00000000000..03da6ba1efb
--- /dev/null
+++ b/core/camel-util/src/test/java/org/apache/camel/util/StopWatchTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.camel.util;
+
+import java.time.Duration;
+import java.util.Date;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class StopWatchTest {
+    @Test
+    void testDurationMatchesExpect() throws InterruptedException {
+        StopWatch stopWatch = new StopWatch();
+
+        Thread.sleep(Duration.ofSeconds(1).toMillis());
+
+        long taken = stopWatch.taken();
+        assertTrue(taken >= 1000, "Elapsed time should be equal to or greater than 1000 ms but was " + taken);
+        assertTrue(taken < 1500, "Elapsed time should be smaller than 1500 ms but was " + taken);
+    }
+
+    @SuppressWarnings("deprecated")
+    @Test
+    void testDurationMatchesExpectWithDate() throws InterruptedException {
+        Date startTime = new Date();
+
+        Thread.sleep(Duration.ofSeconds(1).toMillis());
+
+        long taken = StopWatch.elapsedMillisSince(startTime.getTime());
+        assertTrue(taken >= 1000, "Elapsed time should be equal to or greater than 1000 ms but was " + taken);
+        assertTrue(taken < 1500, "Elapsed time should be smaller than 1500 ms but was " + taken);
+    }
+
+    @Test
+    void testDurationMatchesExpectWithRestart() throws InterruptedException {
+        StopWatch stopWatch = new StopWatch();
+
+        Thread.sleep(Duration.ofSeconds(1).toMillis());
+
+        long taken = stopWatch.taken();
+        assertTrue(taken >= 1000, "Elapsed time should be equal to or greater than 1000 ms but was " + taken);
+        assertTrue(taken < 1500, "Elapsed time should be smaller than 1500 ms but was " + taken);
+
+        stopWatch.restart();
+
+        Thread.sleep(Duration.ofSeconds(1).toMillis());
+
+        taken = stopWatch.taken();
+        assertTrue(taken >= 1000, "Elapsed time should be equal to or greater than 1000 ms but was " + taken);
+        assertTrue(taken < 1500, "Elapsed time should be smaller than 1500 ms but was " + taken);
+    }
+
+    @Test
+    void testDurationMatchesExpectLateStart() throws InterruptedException {
+        StopWatch stopWatch = new StopWatch(false);
+
+        Thread.sleep(Duration.ofSeconds(1).toMillis());
+
+        long taken = stopWatch.taken();
+        assertEquals(0, taken);
+
+        stopWatch.restart();
+
+        Thread.sleep(Duration.ofSeconds(1).toMillis());
+
+        taken = stopWatch.taken();
+        assertTrue(taken >= 1000, "Elapsed time should be equal to or greater than 1000 ms but was " + taken);
+        assertTrue(taken < 1500, "Elapsed time should be smaller than 1500 ms but was " + taken);
+    }
+
+}