forked from j62/ctbrec
1
0
Fork 0

Improve bandwidth meter performance

This commit is contained in:
0xb00bface 2020-12-28 17:34:56 +01:00
parent 5d50515b81
commit c79cc826d7
2 changed files with 37 additions and 62 deletions

View File

@ -366,8 +366,9 @@ public class CamrecApplication extends Application {
private void registerBandwidthMeterListener() { private void registerBandwidthMeterListener() {
BandwidthMeter.addListener((bytes, dur) -> { BandwidthMeter.addListener((bytes, dur) -> {
long seconds = dur.getSeconds(); long millis = dur.toMillis();
bytesPerSecond = bytes / (double)seconds; double bytesPerMilli = bytes / (double)millis;
bytesPerSecond = bytesPerMilli * 1000;
updateStatus(); updateStatus();
}); });
} }

View File

@ -3,46 +3,55 @@ package ctbrec.io;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BandwidthMeter { public class BandwidthMeter {
public static final Duration MEASURE_TIMEFRAME = Duration.ofSeconds(10); public static final Duration MEASURE_TIMEFRAME = Duration.ofSeconds(10);
private static List<Record> records = new ArrayList<>(100); private static long[] records = new long[10000];
private static Lock lock = new ReentrantLock(true); private static int head = 0;
private static int tail = 0;
private static List<Listener> listeners = new ArrayList<>(); private static List<Listener> listeners = new ArrayList<>();
private static Instant lastUpdate = Instant.EPOCH; private static long lastUpdate = 0;
private static long throughput = 0;
private BandwidthMeter() { private BandwidthMeter() {
} }
public static void add(long bytes) { public static synchronized void add(long bytes) {
Record r = new Record(bytes); int idx = getNextIndex();
lock.lock(); records[idx] = bytes;
try {
records.add(r);
} finally {
lock.unlock();
}
Instant oneSecondAgo = Instant.now().minus(Duration.ofSeconds(1)); if (lastUpdate + 1000 < System.currentTimeMillis()) {
if (lastUpdate.isBefore(oneSecondAgo)) { Instant last = Instant.ofEpochMilli(lastUpdate);
fireEvent(getThroughput(), MEASURE_TIMEFRAME); Instant now = Instant.now();
lastUpdate = Instant.now(); Duration d = Duration.between(last, now);
calculateThroughput();
fireEvent(getThroughput(), d);
} }
} }
public static void setThroughput(long bytes, Duration d) { private static void calculateThroughput() {
lock.lock(); throughput = 0;
try { while (tail != head) {
records.clear(); throughput += records[tail++];
records.add(new Record(bytes)); if (tail == records.length) {
} finally { tail = 0;
lock.unlock(); }
} }
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); fireEvent(bytes, d);
} }
@ -57,31 +66,6 @@ public class BandwidthMeter {
* @return throughput in bytes * @return throughput in bytes
*/ */
public static long getThroughput() { 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<Record> 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; return throughput;
} }
@ -93,16 +77,6 @@ public class BandwidthMeter {
listeners.remove(l); listeners.remove(l);
} }
private static class Record {
public Instant timestamp;
public long bytes;
public Record(long bytes) {
timestamp = Instant.now();
this.bytes = bytes;
}
}
@FunctionalInterface @FunctionalInterface
public static interface Listener { public static interface Listener {
void bandwidthCalculated(long bytes, Duration timeframe); void bandwidthCalculated(long bytes, Duration timeframe);