diff options
Diffstat (limited to 'nfvbench/summarizer.py')
-rw-r--r-- | nfvbench/summarizer.py | 215 |
1 files changed, 151 insertions, 64 deletions
diff --git a/nfvbench/summarizer.py b/nfvbench/summarizer.py index 7520076..7c69f52 100644 --- a/nfvbench/summarizer.py +++ b/nfvbench/summarizer.py @@ -47,7 +47,7 @@ def _annotate_chain_stats(chain_stats, nodrop_marker='=>'): In the case of shared net, some columns in packets array can have ''. Some columns cab also be None which means the data is not available. """ - for stats in chain_stats.values(): + for stats in list(chain_stats.values()): packets = stats['packets'] count = len(packets) if count > 1: @@ -97,7 +97,7 @@ class Formatter(object): def standard(data): if isinstance(data, int): return Formatter.int(data) - elif isinstance(data, float): + if isinstance(data, float): return Formatter.float(4)(data) return Formatter.fixed(data) @@ -130,7 +130,7 @@ class Formatter(object): def percentage(data): if data is None: return '' - elif math.isnan(data): + if math.isnan(data): return '-' return Formatter.suffix('%')(Formatter.float(4)(data)) @@ -139,7 +139,7 @@ class Table(object): """ASCII readable table class.""" def __init__(self, header): - header_row, self.formatters = zip(*header) + header_row, self.formatters = list(zip(*header)) self.data = [header_row] self.columns = len(header_row) @@ -195,7 +195,7 @@ class Summarizer(object): def _put_dict(self, data): with self._create_block(False): - for key, value in data.iteritems(): + for key, value in list(data.items()): if isinstance(value, dict): self._put(key + ':') self._put_dict(value) @@ -219,35 +219,6 @@ class Summarizer(object): class NFVBenchSummarizer(Summarizer): """Summarize nfvbench json result.""" - ndr_pdr_header = [ - ('-', Formatter.fixed), - ('L2 Frame Size', Formatter.standard), - ('Rate (fwd+rev)', Formatter.bits), - ('Rate (fwd+rev)', Formatter.suffix(' pps')), - ('Avg Drop Rate', Formatter.suffix('%')), - ('Avg Latency (usec)', Formatter.standard), - ('Min Latency (usec)', Formatter.standard), - ('Max Latency (usec)', Formatter.standard) - ] - - single_run_header = [ - ('L2 Frame Size', Formatter.standard), - ('Drop Rate', Formatter.suffix('%')), - ('Avg Latency (usec)', Formatter.standard), - ('Min Latency (usec)', Formatter.standard), - ('Max Latency (usec)', Formatter.standard) - ] - - config_header = [ - ('Direction', Formatter.standard), - ('Requested TX Rate (bps)', Formatter.bits), - ('Actual TX Rate (bps)', Formatter.bits), - ('RX Rate (bps)', Formatter.bits), - ('Requested TX Rate (pps)', Formatter.suffix(' pps')), - ('Actual TX Rate (pps)', Formatter.suffix(' pps')), - ('RX Rate (pps)', Formatter.suffix(' pps')) - ] - direction_keys = ['direction-forward', 'direction-reverse', 'direction-total'] direction_names = ['Forward', 'Reverse', 'Total'] @@ -259,6 +230,47 @@ class NFVBenchSummarizer(Summarizer): self.record_header = None self.record_data = None self.sender = sender + + self.ndr_pdr_header = [ + ('-', Formatter.fixed), + ('L2 Frame Size', Formatter.standard), + ('Rate (fwd+rev)', Formatter.bits), + ('Rate (fwd+rev)', Formatter.suffix(' pps')), + ('Avg Drop Rate', Formatter.suffix('%')), + ('Avg Latency (usec)', Formatter.standard), + ('Min Latency (usec)', Formatter.standard), + ('Max Latency (usec)', Formatter.standard) + ] + + self.single_run_header = [ + ('L2 Frame Size', Formatter.standard), + ('Drop Rate', Formatter.suffix('%')), + ('Avg Latency (usec)', Formatter.standard), + ('Min Latency (usec)', Formatter.standard), + ('Max Latency (usec)', Formatter.standard) + ] + + self.config_header = [ + ('Direction', Formatter.standard), + ('Requested TX Rate (bps)', Formatter.bits), + ('Actual TX Rate (bps)', Formatter.bits), + ('RX Rate (bps)', Formatter.bits), + ('Requested TX Rate (pps)', Formatter.suffix(' pps')), + ('Actual TX Rate (pps)', Formatter.suffix(' pps')), + ('RX Rate (pps)', Formatter.suffix(' pps')) + ] + + # add percentiles headers if hdrh enabled + if not self.config.disable_hdrh: + for percentile in self.config.lat_percentiles: + # 'append' expects a single parameter => double parentheses + self.ndr_pdr_header.append((str(percentile) + ' %ile lat.', Formatter.standard)) + self.single_run_header.append((str(percentile) + ' %ile lat.', Formatter.standard)) + + if self.config.periodic_gratuitous_arp: + self.direction_keys.insert(2, 'garp-direction-total') + self.direction_names.insert(2, 'Gratuitous ARP') + # if sender is available initialize record if self.sender: self.__record_init() @@ -297,7 +309,7 @@ class NFVBenchSummarizer(Summarizer): if network_benchmark['versions']: self._put('Versions:') with self._create_block(): - for component, version in network_benchmark['versions'].iteritems(): + for component, version in list(network_benchmark['versions'].items()): self._put(component + ':', version) if self.config['ndr_run'] or self.config['pdr_run']: @@ -308,7 +320,7 @@ class NFVBenchSummarizer(Summarizer): if self.config['pdr_run']: self._put('PDR:', self.config['measurement']['PDR']) self._put('Service chain:') - for result in network_benchmark['service_chain'].iteritems(): + for result in list(network_benchmark['service_chain'].items()): with self._create_block(): self.__chain_summarize(*result) @@ -325,13 +337,13 @@ class NFVBenchSummarizer(Summarizer): self._put('Bidirectional:', traffic_benchmark['bidirectional']) self._put('Flow count:', traffic_benchmark['flow_count']) self._put('Service chains count:', traffic_benchmark['service_chain_count']) - self._put('Compute nodes:', traffic_benchmark['compute_nodes'].keys()) + self._put('Compute nodes:', list(traffic_benchmark['compute_nodes'].keys())) self.__record_header_put('profile', traffic_benchmark['profile']) self.__record_header_put('bidirectional', traffic_benchmark['bidirectional']) self.__record_header_put('flow_count', traffic_benchmark['flow_count']) self.__record_header_put('sc_count', traffic_benchmark['service_chain_count']) - self.__record_header_put('compute_nodes', traffic_benchmark['compute_nodes'].keys()) + self.__record_header_put('compute_nodes', list(traffic_benchmark['compute_nodes'].keys())) with self._create_block(False): self._put() if not self.config['no_traffic']: @@ -345,7 +357,7 @@ class NFVBenchSummarizer(Summarizer): except KeyError: pass - for entry in traffic_benchmark['result'].iteritems(): + for entry in list(traffic_benchmark['result'].items()): if 'warning' in entry: continue self.__chain_analysis_summarize(*entry) @@ -391,10 +403,11 @@ class NFVBenchSummarizer(Summarizer): summary_table = Table(self.ndr_pdr_header) if self.config['ndr_run']: - for frame_size, analysis in traffic_result.iteritems(): + for frame_size, analysis in list(traffic_result.items()): if frame_size == 'warning': continue - summary_table.add_row([ + + row_data = [ 'NDR', frame_size, analysis['ndr']['rate_bps'], @@ -403,21 +416,34 @@ class NFVBenchSummarizer(Summarizer): analysis['ndr']['stats']['overall']['avg_delay_usec'], analysis['ndr']['stats']['overall']['min_delay_usec'], analysis['ndr']['stats']['overall']['max_delay_usec'] - ]) - self.__record_data_put(frame_size, {'ndr': { + ] + if not self.config.disable_hdrh: + self.extract_hdrh_percentiles( + analysis['ndr']['stats']['overall']['lat_percentile'], row_data) + summary_table.add_row(row_data) + + ndr_data = { 'type': 'NDR', 'rate_bps': analysis['ndr']['rate_bps'], 'rate_pps': analysis['ndr']['rate_pps'], + 'offered_tx_rate_bps': analysis['ndr']['stats']['offered_tx_rate_bps'], + 'theoretical_tx_rate_pps': analysis['ndr']['stats']['theoretical_tx_rate_pps'], + 'theoretical_tx_rate_bps': analysis['ndr']['stats']['theoretical_tx_rate_bps'], 'drop_percentage': analysis['ndr']['stats']['overall']['drop_percentage'], 'avg_delay_usec': analysis['ndr']['stats']['overall']['avg_delay_usec'], 'min_delay_usec': analysis['ndr']['stats']['overall']['min_delay_usec'], 'max_delay_usec': analysis['ndr']['stats']['overall']['max_delay_usec'] - }}) + } + if not self.config.disable_hdrh: + self.extract_hdrh_percentiles( + analysis['ndr']['stats']['overall']['lat_percentile'], ndr_data, True) + self.__record_data_put(frame_size, {'ndr': ndr_data}) if self.config['pdr_run']: - for frame_size, analysis in traffic_result.iteritems(): + for frame_size, analysis in list(traffic_result.items()): if frame_size == 'warning': continue - summary_table.add_row([ + + row_data = [ 'PDR', frame_size, analysis['pdr']['rate_bps'], @@ -426,34 +452,73 @@ class NFVBenchSummarizer(Summarizer): analysis['pdr']['stats']['overall']['avg_delay_usec'], analysis['pdr']['stats']['overall']['min_delay_usec'], analysis['pdr']['stats']['overall']['max_delay_usec'] - ]) - self.__record_data_put(frame_size, {'pdr': { + ] + if not self.config.disable_hdrh: + self.extract_hdrh_percentiles( + analysis['pdr']['stats']['overall']['lat_percentile'], row_data) + summary_table.add_row(row_data) + + pdr_data = { 'type': 'PDR', 'rate_bps': analysis['pdr']['rate_bps'], 'rate_pps': analysis['pdr']['rate_pps'], + 'offered_tx_rate_bps': analysis['pdr']['stats']['offered_tx_rate_bps'], + 'theoretical_tx_rate_pps': analysis['pdr']['stats']['theoretical_tx_rate_pps'], + 'theoretical_tx_rate_bps': analysis['pdr']['stats']['theoretical_tx_rate_bps'], 'drop_percentage': analysis['pdr']['stats']['overall']['drop_percentage'], 'avg_delay_usec': analysis['pdr']['stats']['overall']['avg_delay_usec'], 'min_delay_usec': analysis['pdr']['stats']['overall']['min_delay_usec'], 'max_delay_usec': analysis['pdr']['stats']['overall']['max_delay_usec'] - }}) + } + if not self.config.disable_hdrh: + self.extract_hdrh_percentiles( + analysis['pdr']['stats']['overall']['lat_percentile'], pdr_data, True) + self.__record_data_put(frame_size, {'pdr': pdr_data}) if self.config['single_run']: - for frame_size, analysis in traffic_result.iteritems(): - summary_table.add_row([ + for frame_size, analysis in list(traffic_result.items()): + row_data = [ frame_size, analysis['stats']['overall']['drop_rate_percent'], analysis['stats']['overall']['rx']['avg_delay_usec'], analysis['stats']['overall']['rx']['min_delay_usec'], analysis['stats']['overall']['rx']['max_delay_usec'] - ]) - self.__record_data_put(frame_size, {'single_run': { + ] + if not self.config.disable_hdrh: + self.extract_hdrh_percentiles( + analysis['stats']['overall']['rx']['lat_percentile'], row_data) + summary_table.add_row(row_data) + + single_run_data = { 'type': 'single_run', + 'offered_tx_rate_bps': analysis['stats']['offered_tx_rate_bps'], + 'theoretical_tx_rate_pps': analysis['stats']['theoretical_tx_rate_pps'], + 'theoretical_tx_rate_bps': analysis['stats']['theoretical_tx_rate_bps'], 'drop_rate_percent': analysis['stats']['overall']['drop_rate_percent'], 'avg_delay_usec': analysis['stats']['overall']['rx']['avg_delay_usec'], 'min_delay_usec': analysis['stats']['overall']['rx']['min_delay_usec'], 'max_delay_usec': analysis['stats']['overall']['rx']['max_delay_usec'] - }}) + } + if not self.config.disable_hdrh: + self.extract_hdrh_percentiles( + analysis['stats']['overall']['rx']['lat_percentile'], single_run_data, True) + self.__record_data_put(frame_size, {'single_run': single_run_data}) return summary_table + def extract_hdrh_percentiles(self, lat_percentile, data, add_key=False): + if add_key: + data['lat_percentile'] = {} + for percentile in self.config.lat_percentiles: + if add_key: + try: + data['lat_percentile_' + str(percentile)] = lat_percentile[percentile] + except TypeError: + data['lat_percentile_' + str(percentile)] = "n/a" + else: + try: + data.append(lat_percentile[percentile]) + except TypeError: + data.append("n/a") + def __get_config_table(self, run_config, frame_size): config_table = Table(self.config_header) for key, name in zip(self.direction_keys, self.direction_names): @@ -485,11 +550,11 @@ class NFVBenchSummarizer(Summarizer): chain_stats: { 'interfaces': ['Port0', 'drop %'', 'vhost0', 'Port1'], 'chains': { - 0: {'packets': [2000054, '-0.023%', 1999996, 1999996], + '0': {'packets': [2000054, '-0.023%', 1999996, 1999996], 'lat_min_usec': 10, 'lat_max_usec': 187, 'lat_avg_usec': 45}, - 1: {...}, + '1': {...}, 'total': {...} } } @@ -498,21 +563,43 @@ class NFVBenchSummarizer(Summarizer): _annotate_chain_stats(chains) header = [('Chain', Formatter.standard)] + \ [(ifname, Formatter.standard) for ifname in chain_stats['interfaces']] - # add latency columns if available Avg, Min, Max + # add latency columns if available Avg, Min, Max and percentiles lat_keys = [] lat_map = {'lat_avg_usec': 'Avg lat.', 'lat_min_usec': 'Min lat.', 'lat_max_usec': 'Max lat.'} - if 'lat_avg_usec' in chains[0]: + if 'lat_avg_usec' in chains['0']: lat_keys = ['lat_avg_usec', 'lat_min_usec', 'lat_max_usec'] - for key in lat_keys: - header.append((lat_map[key], Formatter.standard)) + + if not self.config.disable_hdrh: + lat_keys.append('lat_percentile') + for percentile in self.config.lat_percentiles: + lat_map['lat_' + str(percentile) + '_percentile'] = \ + str(percentile) + ' %ile lat.' + + for lat_value in lat_map.values(): + # 'append' expects a single parameter => double parentheses + header.append((lat_value, Formatter.standard)) table = Table(header) - for chain in sorted(chains.keys()): + for chain in sorted(list(chains.keys()), key=str): row = [chain] + chains[chain]['packets'] for lat_key in lat_keys: - row.append('{:,} usec'.format(chains[chain][lat_key])) + + if lat_key != 'lat_percentile': + if chains[chain].get(lat_key, None): + row.append(Formatter.standard(chains[chain][lat_key])) + else: + row.append('n/a') + else: + if not self.config.disable_hdrh: + if chains[chain].get(lat_key, None): + for percentile in chains[chain][lat_key]: + row.append(Formatter.standard( + chains[chain][lat_key][percentile])) + else: + for _ in self.config.lat_percentiles: + row.append('n/a') table.add_row(row) return table @@ -546,9 +633,9 @@ class NFVBenchSummarizer(Summarizer): run_specific_data['pdr'] = data['pdr'] run_specific_data['pdr']['drop_limit'] = self.config['measurement']['PDR'] del data['pdr'] - for key in run_specific_data: + for data_value in run_specific_data.values(): data_to_send = data.copy() - data_to_send.update(run_specific_data[key]) + data_to_send.update(data_value) self.sender.record_send(data_to_send) self.__record_init() |