Commit 5fadd42a authored by rna's avatar rna
Browse files

Improve evaluation script.

parent a6f4b002
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
import sys
sys.path.insert(0, "./build")

import time
import tests.perf as perf

def run_setup_and_report(setup):
    results = setup.run()
    print("Setup:\n   ", setup)
    print("    Parameters:\n       ", setup)
    print("    Results:\n        " + str(results).replace("\n","\n        "))

if __name__ == "__main__":
@@ -13,8 +14,16 @@ if __name__ == "__main__":

    # TODO: support multiple tests via proper socket termination
    setups = [
        perf.TestSetup(packets=2**10,delay=0,loss=30,reorder=0,duplicate=0)
        #perf.TestSetup(packets=100,delay=0,loss=0,reorder=0,duplicate=0),         # smoke test
        #perf.TestSetup(packets=500,delay=10,loss=1,reorder=0,duplicate=0),        # stability
        #perf.TestSetup(packets=2**11,delay=0,loss=0,reorder=0,duplicate=0),       # smoke test
        perf.TestSetup(packets=100,delay=10,loss=50,reorder=0,duplicate=0, packet_interval=0.01)      # freaky
    ]

    i = 1
    for setup in setups:
        print("Setup #%d:" % i)
        run_setup_and_report(setup)
        i += 1
        time.sleep(2)
        print("\n")
+1 −1
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ cdef class PrrtSocket:
                raise Exception("Not a sender.")
            return cprrt.PrrtSocket_get_rtt(self._c_socket) * 0.000001

    def recv(self):
    def recv(self, wait_time):
        cdef char buffer[65536]
        cdef int32_t len
        with nogil:
+32 −21
Original line number Diff line number Diff line
@@ -21,8 +21,12 @@ class ReceiverThread(threading.Thread):
        self.receivedPackets[:] = np.NAN

    def run(self):
        while(1):
            data = self.sock.recv()
        while(self.running):
            try:
                data = self.sock.recv(1000000)
            except prrt.TimeoutException:
                continue

            v = data.decode('UTF-8')
            seqno = v[:self.seqnoDigits]
            if seqno in self.received:
@@ -34,11 +38,12 @@ class ReceiverThread(threading.Thread):


class SenderThread(threading.Thread):
    def __init__(self, seqnoDigits, packetCount):
    def __init__(self, seqnoDigits, packetCount, packetInterval):
        threading.Thread.__init__(self)
        self.sock = prrt.PrrtSocket(7005, True, 1)
        self.packetCount = packetCount
        self.seqnoDigits = seqnoDigits
        self.packetInterval = packetInterval

        self.sentPackets = np.ndarray((packetCount),dtype="datetime64[us]")
        self.sentPackets[:] = np.NAN
@@ -46,26 +51,30 @@ class SenderThread(threading.Thread):
        # TODO: create proper arrays

    def run(self):
        self.sock.connect("127.244.0.1", 7000)
        self.sock.connect("127.0.0.1", 7000)
        for i in range(self.packetCount):
            d = str(i).zfill(self.seqnoDigits).encode("UTF-8")
            self.sentPackets[i] = datetime.datetime.now()
            self.sock.send(d)
            time.sleep(0.00001)
            time.sleep(self.packetInterval)

class TestResults(object):
    def __init__(self):
    def __init__(self, showLossPattern=True):
        self.loss = 0
        self.packetsSent = 0
        self.packetsReceived = 0
        self.duplicates = 0
        self.delays = None
        self.showLossPattern = showLossPattern

    def __str__(self):
        delayValues = self.delays[~np.isnan(self.delays)]
        plr = 1 - (self.packetsReceived / self.packetsSent)
        loss = "Residual Loss: %f%% (received %d of %d)" % (plr * 100, self.packetsReceived, self.packetsSent)
        loss = "Residual Loss: %f%% (received %d / %d)" % (plr * 100, self.packetsReceived, self.packetsSent)
        duplicates = "Duplicates: %d" % (self.duplicates)
        if len(delayValues) == 0:
            return "No packets successfully transmitted."

        delayMean = np.mean(delayValues) * 1000
        delayStd = np.std(delayValues) * 1000
        delayMin = np.min(delayValues) * 1000
@@ -84,38 +93,40 @@ class TestResults(object):
        return "%s\n%s\n%s\n%s" % (loss, duplicates, delays, losses)

class TestSetup(object):
    def __init__(self,packets=20,delay=1,delay_variation=0,delay_correlation=0,loss=0,loss_correlation=0,duplicate=0,reorder=0,reorder_correlation=0):
    def __init__(self, packets=20, packet_interval=0.0001, delay=1, delay_variation=0, delay_correlation=0, loss=0, loss_correlation=0, duplicate=0, reorder=0, reorder_correlation=0, loss_pattern=True):
        self.packets = packets
        self.delay = delay
        self.delay_variation = delay_variation
        self.delay_correlation = delay_correlation
        self.delayVariation = delay_variation
        self.delayCorrelation = delay_correlation
        self.loss = loss
        self.loss_correlation = loss_correlation
        self.lossCorrelation = loss_correlation
        self.duplicate = duplicate
        self.reorder = reorder
        self.reorder_correlation = reorder_correlation
        self.processing_delay = 0.0001 # in ms
        self.reorderCorrelation = reorder_correlation
        self.packetInterval = packet_interval # in s
        self.processingDelay = packet_interval

    def netem_config(self):
    def netemConfigString(self):
        # http://www.linuxfoundation.org/collaborate/workgroups/networking/netem
        return "delay %dus %dus %d%% loss %f%% %f%% duplicate %f%% reorder %f%% %f%%" % (
            self.delay, self.delay_variation, self.delay_correlation, self.loss, self.loss_correlation,
            self.duplicate, self.reorder, self.reorder_correlation)
            self.delay, self.delayVariation, self.delayCorrelation, self.loss, self.lossCorrelation,
            self.duplicate, self.reorder, self.reorderCorrelation)

    def run(self):
        # TODO: create and apply only to specific traffic
        subprocess.run("tc qdisc add dev lo root netem " + self.netem_config(), shell=True)
        subprocess.run("tc qdisc add dev lo root netem " + self.netemConfigString(), shell=True)

        seqnoDigits = math.ceil(math.log10(self.packets))
        recvThread = ReceiverThread(seqnoDigits, self.packets)
        recvThread.daemon = True
        sendThread = SenderThread(seqnoDigits, self.packets)
        sendThread = SenderThread(seqnoDigits, self.packets, self.packetInterval)

        recvThread.start()
        sendThread.run()

        recvThread.running = False
        time.sleep(1)
        #time.sleep(1 + self.packets * (self.delay / (1000**2) + self.processing_delay))

        count = len(recvThread.received)

        diffs = map(lambda x: x.item().total_seconds() if x.item() is not None else np.NAN,
@@ -124,7 +135,7 @@ class TestSetup(object):

        subprocess.run("tc qdisc del dev lo root", shell=True, check=True)

        results = TestResults()
        results = TestResults(showLossPattern=self.showLossPattern)
        results.packetsSent = self.packets
        results.packetsReceived = count
        results.duplicates = recvThread.duplicates
@@ -132,4 +143,4 @@ class TestSetup(object):
        return results

    def __str__(self):
        return self.netem_config()
        return self.netemConfigString()