Improve bandwidth meter performance
This commit is contained in:
parent
5d50515b81
commit
c79cc826d7
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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<Record> 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<Listener> 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<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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue