pounder_test/scripts/stream_throughput.py

112 lines
2.8 KiB
Python

#!/usr/bin/python3
"""
Author: Ryan Summers
Description: Provides a mechanism for measuring Stabilizer stream data throughput.
"""
import argparse
import logging
import sys
import time
from stabilizer.stream import StabilizerStream
class Timer:
""" A basic timer for measuring elapsed time periods. """
def __init__(self, period=1.0):
""" Create the timer with the provided period. """
self.start_time = time.time()
self.trigger_time = self.start_time + period
self.period = period
self.started = False
def is_triggered(self):
""" Check if the timer period has elapsed. """
now = time.time()
return now >= self.trigger_time
def start(self):
""" Start the timer. """
self.start_time = time.time()
self.started = True
def is_started(self):
""" Check if the timer has started. """
return self.started
def arm(self):
""" Arm the timer trigger. """
self.trigger_time = time.time() + self.period
def elapsed(self):
""" Get the elapsed time since the timer was started. """
now = time.time()
return now - self.start_time
def sequence_delta(previous_sequence, next_sequence):
""" Check the number of items between two sequence numbers. """
if previous_sequence is None:
return 0
delta = next_sequence - (previous_sequence + 1)
return delta & 0xFFFFFFFF
def main():
""" Main program. """
parser = argparse.ArgumentParser(description='Measure Stabilizer livestream quality')
parser.add_argument('--port', type=int, default=2000,
help='The port that stabilizer is streaming to')
args = parser.parse_args()
logging.basicConfig(level=logging.INFO,
format='%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s')
last_index = None
drop_count = 0
good_blocks = 0
total_bytes = 0
timer = Timer()
stream = StabilizerStream(args.port)
while True:
# Receive any data over UDP and parse it.
for (seqnum, _) in stream.read_frame():
if not timer.is_started():
timer.start()
# Handle any dropped packets.
drop_count += sequence_delta(last_index, seqnum)
last_index = seqnum
good_blocks += 1
# Report the throughput periodically.
if timer.is_triggered():
drate = stream.get_rx_bytes() * 8 / 1e6 / timer.elapsed()
print(f'''
Data Rate: {drate:.3f} Mbps
Received Blocks: {good_blocks}
Dropped blocks: {drop_count}
Metadata: {total_bytes / 1e6:.3f} MB in {timer.elapsed():.2f} s
----
''')
sys.stdout.flush()
timer.arm()
if __name__ == '__main__':
main()