From c79cc826d7f290cdfecdbd582bfab2639b15912f Mon Sep 17 00:00:00 2001 From: 0xb00bface <0xboobface@gmail.com> Date: Mon, 28 Dec 2020 17:34:56 +0100 Subject: [PATCH] Improve bandwidth meter performance --- .../java/ctbrec/ui/CamrecApplication.java | 5 +- .../main/java/ctbrec/io/BandwidthMeter.java | 94 +++++++------------ 2 files changed, 37 insertions(+), 62 deletions(-) diff --git a/client/src/main/java/ctbrec/ui/CamrecApplication.java b/client/src/main/java/ctbrec/ui/CamrecApplication.java index 1278e97d..a02b75c6 100644 --- a/client/src/main/java/ctbrec/ui/CamrecApplication.java +++ b/client/src/main/java/ctbrec/ui/CamrecApplication.java @@ -366,8 +366,9 @@ public class CamrecApplication extends Application { private void registerBandwidthMeterListener() { BandwidthMeter.addListener((bytes, dur) -> { - long seconds = dur.getSeconds(); - bytesPerSecond = bytes / (double)seconds; + long millis = dur.toMillis(); + double bytesPerMilli = bytes / (double)millis; + bytesPerSecond = bytesPerMilli * 1000; updateStatus(); }); } diff --git a/common/src/main/java/ctbrec/io/BandwidthMeter.java b/common/src/main/java/ctbrec/io/BandwidthMeter.java index 779556c7..58472330 100644 --- a/common/src/main/java/ctbrec/io/BandwidthMeter.java +++ b/common/src/main/java/ctbrec/io/BandwidthMeter.java @@ -3,46 +3,55 @@ package ctbrec.io; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; public class BandwidthMeter { public static final Duration MEASURE_TIMEFRAME = Duration.ofSeconds(10); - private static List records = new ArrayList<>(100); - private static Lock lock = new ReentrantLock(true); + private static long[] records = new long[10000]; + private static int head = 0; + private static int tail = 0; private static List listeners = new ArrayList<>(); - private static Instant lastUpdate = Instant.EPOCH; + private static long lastUpdate = 0; + private static long throughput = 0; private BandwidthMeter() { } - public static void add(long bytes) { - Record r = new Record(bytes); - lock.lock(); - try { - records.add(r); - } finally { - lock.unlock(); - } + public static synchronized void add(long bytes) { + int idx = getNextIndex(); + records[idx] = bytes; - Instant oneSecondAgo = Instant.now().minus(Duration.ofSeconds(1)); - if (lastUpdate.isBefore(oneSecondAgo)) { - fireEvent(getThroughput(), MEASURE_TIMEFRAME); - lastUpdate = Instant.now(); + if (lastUpdate + 1000 < System.currentTimeMillis()) { + Instant last = Instant.ofEpochMilli(lastUpdate); + Instant now = Instant.now(); + Duration d = Duration.between(last, now); + calculateThroughput(); + fireEvent(getThroughput(), d); } } - public static void setThroughput(long bytes, Duration d) { - lock.lock(); - try { - records.clear(); - records.add(new Record(bytes)); - } finally { - lock.unlock(); + private static void calculateThroughput() { + throughput = 0; + while (tail != head) { + throughput += records[tail++]; + if (tail == records.length) { + tail = 0; + } } + lastUpdate = System.currentTimeMillis(); + } + + private static int getNextIndex() { + head++; + if(head == records.length) { + head = 0; + } + return head; + } + + public static void setThroughput(long bytes, Duration d) { + records[0] = bytes; fireEvent(bytes, d); } @@ -57,31 +66,6 @@ public class BandwidthMeter { * @return throughput in bytes */ public static long getThroughput() { - return getThroughput(MEASURE_TIMEFRAME); - } - - /** - * Get the throughput over the given duration - * @return throughput in bytes - */ - public static long getThroughput(Duration d) { - Instant now = Instant.now(); - Instant measureStart = now.minus(d); - long throughput = 0; - lock.lock(); - try { - for (Iterator iterator = records.iterator(); iterator.hasNext();) { - Record record = iterator.next(); - if (record.timestamp.isBefore(measureStart)) { - iterator.remove(); - } else { - throughput += record.bytes; - } - } - - } finally { - lock.unlock(); - } return throughput; } @@ -93,16 +77,6 @@ public class BandwidthMeter { listeners.remove(l); } - private static class Record { - public Instant timestamp; - public long bytes; - - public Record(long bytes) { - timestamp = Instant.now(); - this.bytes = bytes; - } - } - @FunctionalInterface public static interface Listener { void bandwidthCalculated(long bytes, Duration timeframe);