From 6d5cdbafca1e5bad685ed51504996c42b4ff44fa Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Fri, 30 Jul 2021 19:45:44 +0200 Subject: [PATCH] FastTime a faster alternative to System.currentTimeMillis FastTime is 100 times faster (according to my primitive benchmark) than System.currentTimeMillis. It is less accurate. --- .../main/java/org/lucares/utils/FastTime.java | 81 +++++++++++++++++++ .../lucares/performance/db/PerformanceDb.java | 9 ++- 2 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 pdb-utils/src/main/java/org/lucares/utils/FastTime.java diff --git a/pdb-utils/src/main/java/org/lucares/utils/FastTime.java b/pdb-utils/src/main/java/org/lucares/utils/FastTime.java new file mode 100644 index 0000000..cf3b6d3 --- /dev/null +++ b/pdb-utils/src/main/java/org/lucares/utils/FastTime.java @@ -0,0 +1,81 @@ +package org.lucares.utils; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +/** + * Faster than {@link System#currentTimeMillis()}, but with a lower resolution. + */ +public class FastTime { + private static final class TimeUpdaterThread extends Thread { + + private static final long UPDATE_INTERVAL = Duration.ofMillis(50).toMillis(); + + public TimeUpdaterThread() { + setDaemon(true); + setName("fast-time"); + } + + @Override + public void run() { + while (true) { + try { + TimeUnit.MILLISECONDS.sleep(UPDATE_INTERVAL); + currentTimeMillis = System.currentTimeMillis(); + } catch (final InterruptedException e) { + // interrupted -> abort + } + } + } + } + + private volatile static long currentTimeMillis = System.currentTimeMillis(); + + static { + new TimeUpdaterThread().start(); + } + + public static long currentTimeMillis() { + return currentTimeMillis; + } + + /** + *
+     * ---------------------------------------- 
+     * Benchmark:
+     * fastTime   took: 0.024366 ms -> sum = 162766570282900000
+     * timeMillis took: 2.587725 ms -> sum = 162766570283110644
+     * timeMillis / fastTime = 106.20229007633587
+     * 
+ */ + + public static void main(final String[] args) { + for (int i = 0; i < 100; i++) { + final double f = fastTime(); + final double t = timeMillis(); + System.out.println("t / f = " + (t / f)); + } + } + + private static double fastTime() { + final long start = System.nanoTime(); + long sum = 0; + for (int j = 0; j < 100000; j++) { + sum += FastTime.currentTimeMillis(); + } + final double duration = (System.nanoTime() - start) / 1_000_000.0; + System.out.println("fastTime took: " + duration + " ms -> sum = " + sum); + return duration; + } + + private static double timeMillis() { + final long start = System.nanoTime(); + long sum = 0; + for (int j = 0; j < 100000; j++) { + sum += System.currentTimeMillis(); + } + final double duration = (System.nanoTime() - start) / 1_000_000.0; + System.out.println("timeMillis took: " + duration + " ms -> sum = " + sum); + return duration; + } +} diff --git a/performanceDb/src/main/java/org/lucares/performance/db/PerformanceDb.java b/performanceDb/src/main/java/org/lucares/performance/db/PerformanceDb.java index e8aab8f..82a05cf 100644 --- a/performanceDb/src/main/java/org/lucares/performance/db/PerformanceDb.java +++ b/performanceDb/src/main/java/org/lucares/performance/db/PerformanceDb.java @@ -31,6 +31,7 @@ import org.lucares.pdb.datastore.WriteException; import org.lucares.pdb.datastore.internal.DataStore; import org.lucares.pdb.datastore.internal.PartitionDiskStore; import org.lucares.pdb.datastore.lang.SyntaxException; +import org.lucares.utils.FastTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -94,7 +95,7 @@ public class PerformanceDb implements AutoCloseable { long insertionsSinceLastSync = 0; try { - long lastSync = System.currentTimeMillis(); + long lastSync = FastTime.currentTimeMillis(); long nextSync = lastSync + timeBetweenSyncs.toMillis(); while (true) { @@ -116,15 +117,15 @@ public class PerformanceDb implements AutoCloseable { count++; insertionsSinceLastSync++; - if (nextSync <= System.currentTimeMillis()) { - final long end = System.currentTimeMillis(); + if (nextSync <= FastTime.currentTimeMillis()) { + final long end = FastTime.currentTimeMillis(); final long duration = end - lastSync; final long entriesPerSecond = (long) (insertionsSinceLastSync / (duration / 1000.0)); METRICS_LOGGER.debug(String.format(Locale.US, "inserting %,11d/s ; total: %,d; last: %s", entriesPerSecond, count, entry)); - lastSync = System.currentTimeMillis(); + lastSync = FastTime.currentTimeMillis(); nextSync = lastSync + timeBetweenSyncs.toMillis(); insertionsSinceLastSync = 0; }