/*******************************************************************************
* gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/
* Copyright (C) 2014 SVS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package userGeneratedContent.testbedPlugIns.layerPlugIns.layer2recodingScheme.encDNS_v0_001;
import java.util.concurrent.TimeUnit;
public class StatisticsRecorder {
private static boolean DISPLAY_THROUGHPUT;
private static boolean DISPLAY_PACKETS;
private static int DISPLAY_STAT_PERIOD;
private static long[] sumOfRequestDataReceivedInPeriod;
private static long[] sumOfReplyDataReceivedInPeriod;
private static long sumOfRequestDataReceivedInTotal = 0;
private static long sumOfReplyDataReceivedInTotal = 0;
private static int[] requestPacketCounterPeriod;
private static int[] replyPacketCounterPeriod;
private static int requestPacketCounterTotal = 0;
private static int replyPacketCounterTotal = 0;
private static Object[] synchronizers;
private static long startTime;
private static int treadIdCounter = -1;
public static void init(boolean DISPLAY_THROUGHPUT, boolean DISPLAY_PACKETS, int DISPLAY_STAT_PERIOD, int NUMBER_OF_THREADS) {
StatisticsRecorder.DISPLAY_THROUGHPUT = DISPLAY_THROUGHPUT;
StatisticsRecorder.DISPLAY_PACKETS = DISPLAY_PACKETS;
StatisticsRecorder.DISPLAY_STAT_PERIOD = DISPLAY_STAT_PERIOD;
sumOfRequestDataReceivedInPeriod = new long[NUMBER_OF_THREADS];
sumOfReplyDataReceivedInPeriod = new long[NUMBER_OF_THREADS];
requestPacketCounterPeriod = new int[NUMBER_OF_THREADS];
replyPacketCounterPeriod = new int[NUMBER_OF_THREADS];
synchronizers = new Object[NUMBER_OF_THREADS];
for (int i=0; i<synchronizers.length; i++)
synchronizers[i] = new Object();
if (DISPLAY_THROUGHPUT || DISPLAY_PACKETS)
new DisplayThread().start();
}
public static void addRequestThroughputRecord(int ammountOfData, int threadId) {
if (DISPLAY_THROUGHPUT || DISPLAY_PACKETS) {
synchronized (synchronizers[threadId]) {
sumOfRequestDataReceivedInPeriod[threadId] += ammountOfData;
requestPacketCounterPeriod[threadId]++;
}
}
}
public static void addReplyThroughputRecord(int ammountOfData, int threadId) {
if (DISPLAY_THROUGHPUT || DISPLAY_PACKETS) {
synchronized (synchronizers[threadId]) {
sumOfReplyDataReceivedInPeriod[threadId] += ammountOfData;
replyPacketCounterPeriod[threadId]++;
}
}
}
static class DisplayThread extends Thread {
@Override
public void run() {
startTime = System.nanoTime();
while (true) {
try {
Thread.sleep(DISPLAY_STAT_PERIOD);
} catch (InterruptedException e) {
e.printStackTrace();
continue;
}
System.out.println("STATISTICS:" +getStatistics());
}
}
private String getStatistics() {
String output = "";
long duration = TimeUnit.MILLISECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
// aggregate data:
long sumOfRequestDataP = 0;
long sumOfReplyDataP = 0;
int requestPacketCounterP = 0;
int replyPacketCounterP = 0;
for (int i=0; i<synchronizers.length; i++) {
synchronized (synchronizers[i]) {
sumOfRequestDataP += sumOfRequestDataReceivedInPeriod[i];
sumOfRequestDataReceivedInPeriod[i] = 0;
sumOfReplyDataP += sumOfReplyDataReceivedInPeriod[i];
sumOfReplyDataReceivedInPeriod[i] = 0;
requestPacketCounterP += requestPacketCounterPeriod[i];
requestPacketCounterPeriod[i] = 0;
replyPacketCounterP += replyPacketCounterPeriod[i];
replyPacketCounterPeriod[i] = 0;
}
}
if (DISPLAY_THROUGHPUT) {
sumOfRequestDataReceivedInTotal += sumOfRequestDataP;
sumOfReplyDataReceivedInTotal += sumOfReplyDataP;
output += "\n total request-THROUGHPUT: ";
output += humanReadableByteCount((sumOfRequestDataP/duration)*1000, false) +"/sec";
output += " (" +humanReadableByteCount((sumOfRequestDataP/duration)*1000, true) +"/sec";
output += ", measurePeriod: "+duration +" ms";
output += ", transmitted so far: " +humanReadableByteCount(sumOfRequestDataReceivedInTotal, false) +" = " +humanReadableByteCount(sumOfRequestDataReceivedInTotal, true);
output += ")";
if (sumOfReplyDataP != 0) {
output += "\n total reply-THROUGHPUT: ";
output += humanReadableByteCount((sumOfReplyDataP/duration)*1000, false) +"/sec";
output += " (" +humanReadableByteCount((sumOfReplyDataP/duration)*1000, true) +"/sec";
output += ", measurePeriod: "+duration +" ms";
output += ", transmitted so far: " +humanReadableByteCount(sumOfReplyDataReceivedInTotal, false) +" = " +humanReadableByteCount(sumOfReplyDataReceivedInTotal, true);
output += ")";
}
}
if (DISPLAY_PACKETS) {
requestPacketCounterTotal += requestPacketCounterP;
replyPacketCounterTotal += replyPacketCounterP;
output += "\n total requests/sec: ";
output += (((double)requestPacketCounterP/(double)duration)*1000d);
output += ", measurePeriod: "+duration +" ms";
output += ", total request packets so far: " +requestPacketCounterTotal;
output += ")";
if (replyPacketCounterTotal != 0) {
output += "\n total replies/sec: ";
output += ((double)(replyPacketCounterP/(double)duration)*1000d);
output += ", measurePeriod: "+duration +" ms";
output += ", total request packets so far: " +replyPacketCounterTotal;
output += ")";
}
}
startTime = System.nanoTime();
return output;
}
}
public static synchronized int getThreadId() {
return ++treadIdCounter;
}
public static String humanReadableByteCount(long bytes, boolean si) {
// see http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
int unit = si ? 1000 : 1024;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
}