forked from j62/ctbrec
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() {
|
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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue