From 4787ec6f590a94ba997097286bbfeb86e8eeba01 Mon Sep 17 00:00:00 2001 From: Tibor Frank Date: Fri, 24 Apr 2020 10:10:45 +0200 Subject: Trending: NDRPDR weekly comparison Change-Id: I6c5166e1fabfe7471af92a1423c0c89ca6b040a4 Signed-off-by: Tibor Frank (cherry picked from commit 51b4c826796b9f1f3267a0d6a8f2ba796c24d8d4) (cherry picked from commit e260db588739d80e4a8c46c6aba80425bc11b96e) --- resources/tools/presentation/generator_tables.py | 188 ++++++++++++++++++++++- 1 file changed, 182 insertions(+), 6 deletions(-) (limited to 'resources/tools/presentation/generator_tables.py') diff --git a/resources/tools/presentation/generator_tables.py b/resources/tools/presentation/generator_tables.py index d48cea4795..72d93f8247 100644 --- a/resources/tools/presentation/generator_tables.py +++ b/resources/tools/presentation/generator_tables.py @@ -33,7 +33,7 @@ from numpy import nan, isnan from yaml import load, FullLoader, YAMLError from pal_utils import mean, stdev, classify_anomalies, \ - convert_csv_to_pretty_txt, relative_change_stdev + convert_csv_to_pretty_txt, relative_change_stdev, relative_change REGEX_NIC = re.compile(r'(\d*ge\dp\d\D*\d*[a-z]*)') @@ -60,12 +60,15 @@ def generate_tables(spec, data): u"table_failed_tests": table_failed_tests, u"table_failed_tests_html": table_failed_tests_html, u"table_oper_data_html": table_oper_data_html, - u"table_comparison": table_comparison + u"table_comparison": table_comparison, + u"table_weekly_comparison": table_weekly_comparison } logging.info(u"Generating the tables ...") for table in spec.tables: try: + if table[u"algorithm"] == u"table_weekly_comparison": + table[u"testbeds"] = spec.environment.get(u"testbeds", None) generator[table[u"algorithm"]](table, data) except NameError as err: logging.error( @@ -490,7 +493,8 @@ def _tpc_sort_table(table): def _tpc_generate_html_table(header, data, out_file_name, legend=u"", - footnote=u"", sort_data=True, title=u""): + footnote=u"", sort_data=True, title=u"", + generate_rst=True): """Generate html table from input data with simple sorting possibility. :param header: Table header. @@ -504,6 +508,7 @@ def _tpc_generate_html_table(header, data, out_file_name, legend=u"", :param footnote: The footnote to display below the table (and legend). :param sort_data: If True the data sorting is enabled. :param title: The table (and file) title. + :param generate_rst: If True, wrapping rst file is generated. :type header: list :type data: list of lists :type out_file_name: str @@ -511,6 +516,7 @@ def _tpc_generate_html_table(header, data, out_file_name, legend=u"", :type footnote: str :type sort_data: bool :type title: str + :type generate_rst: bool """ try: @@ -528,7 +534,7 @@ def _tpc_generate_html_table(header, data, out_file_name, legend=u"", [u"left", u"left", u"right"], [u"left", u"left", u"left", u"right"] ), - u"width": ([28, 9], [4, 24, 10], [4, 4, 32, 10]) + u"width": ([15, 9], [4, 24, 10], [4, 4, 32, 10]) } df_data = pd.DataFrame(data, columns=header) @@ -599,8 +605,8 @@ def _tpc_generate_html_table(header, data, out_file_name, legend=u"", direction=u"down", x=0.0, xanchor=u"left", - y=1.045, - yanchor=u"top", + y=1.002, + yanchor=u"bottom", active=len(menu_items) - 1, buttons=list(buttons) ) @@ -630,6 +636,9 @@ def _tpc_generate_html_table(header, data, out_file_name, legend=u"", filename=f"{out_file_name}_in.html" ) + if not generate_rst: + return + file_name = out_file_name.split(u"/")[-1] if u"vpp" in out_file_name: path = u"_tmp/src/vpp_performance_tests/comparisons/" @@ -2690,3 +2699,170 @@ def table_comparison(table, input_data): sort_data=False, title=table.get(u"title", u"") ) + + +def table_weekly_comparison(table, in_data): + """Generate the table(s) with algorithm: table_weekly_comparison + specified in the specification file. + + :param table: Table to generate. + :param in_data: Data to process. + :type table: pandas.Series + :type in_data: InputData + """ + logging.info(f" Generating the table {table.get(u'title', u'')} ...") + + # Transform the data + logging.info( + f" Creating the data set for the {table.get(u'type', u'')} " + f"{table.get(u'title', u'')}." + ) + + incl_tests = table.get(u"include-tests", None) + if incl_tests not in (u"NDR", u"PDR"): + logging.error(f"Wrong tests to include specified ({incl_tests}).") + return + + nr_cols = table.get(u"nr-of-data-columns", None) + if not nr_cols or nr_cols < 2: + logging.error( + f"No columns specified for {table.get(u'title', u'')}. Skipping." + ) + return + + data = in_data.filter_data( + table, + params=[u"throughput", u"result", u"name", u"parent", u"tags"], + continue_on_error=True + ) + + header = [ + [u"Version"], + [u"Date", ], + [u"Build", ], + [u"Testbed", ] + ] + tbl_dict = dict() + idx = 0 + tb_tbl = table.get(u"testbeds", None) + for job_name, job_data in data.items(): + for build_nr, build in job_data.items(): + if idx >= nr_cols: + break + if build.empty: + continue + + tb_ip = in_data.metadata(job_name, build_nr).get(u"testbed", u"") + if tb_ip and tb_tbl: + testbed = tb_tbl.get(tb_ip, u"") + else: + testbed = u"" + header[2].insert(1, build_nr) + header[3].insert(1, testbed) + header[1].insert( + 1, in_data.metadata(job_name, build_nr).get(u"generated", u"") + ) + header[0].insert( + 1, in_data.metadata(job_name, build_nr).get(u"version", u"") + ) + + for tst_name, tst_data in build.items(): + tst_name_mod = \ + _tpc_modify_test_name(tst_name).replace(u"2n1l-", u"") + if not tbl_dict.get(tst_name_mod, None): + tbl_dict[tst_name_mod] = dict( + name=tst_data[u'name'].rsplit(u'-', 1)[0], + ) + try: + tbl_dict[tst_name_mod][-idx - 1] = \ + tst_data[u"throughput"][incl_tests][u"LOWER"] + except (TypeError, IndexError, KeyError, ValueError): + pass + idx += 1 + + if idx < nr_cols: + logging.error(u"Not enough data to build the table! Skipping") + return + + cmp_dict = dict() + for idx, cmp in enumerate(table.get(u"comparisons", list())): + idx_ref = cmp.get(u"reference", None) + idx_cmp = cmp.get(u"compare", None) + if idx_ref is None or idx_cmp is None: + continue + header[0].append(f"Diff{idx + 1}") + header[1].append(header[0][idx_ref - idx - 1]) + header[2].append(u"vs") + header[3].append(header[0][idx_cmp - idx - 1]) + for tst_name, tst_data in tbl_dict.items(): + if not cmp_dict.get(tst_name, None): + cmp_dict[tst_name] = list() + ref_data = tst_data.get(idx_ref, None) + cmp_data = tst_data.get(idx_cmp, None) + if ref_data is None or cmp_data is None: + cmp_dict[tst_name].append(float('nan')) + else: + cmp_dict[tst_name].append( + relative_change(ref_data, cmp_data) + ) + + tbl_lst = list() + for tst_name, tst_data in tbl_dict.items(): + itm_lst = [tst_data[u"name"], ] + for idx in range(nr_cols): + item = tst_data.get(-idx - 1, None) + if item is None: + itm_lst.insert(1, None) + else: + itm_lst.insert(1, round(item / 1e6, 1)) + itm_lst.extend( + [ + None if itm is None else round(itm, 1) + for itm in cmp_dict[tst_name] + ] + ) + tbl_lst.append(itm_lst) + + tbl_lst.sort(key=lambda rel: rel[0], reverse=False) + tbl_lst.sort(key=lambda rel: rel[-1], reverse=True) + + # Generate csv table: + csv_file = f"{table[u'output-file']}.csv" + with open(csv_file, u"wt", encoding='utf-8') as file_handler: + for hdr in header: + file_handler.write(u",".join(hdr) + u"\n") + for test in tbl_lst: + file_handler.write(u",".join( + [ + str(item).replace(u"None", u"-").replace(u"nan", u"-"). + replace(u"null", u"-") for item in test + ] + ) + u"\n") + + txt_file = f"{table[u'output-file']}.txt" + convert_csv_to_pretty_txt(csv_file, txt_file, delimiter=u",") + + # Reorganize header in txt table + txt_table = list() + with open(txt_file, u"rt", encoding='utf-8') as file_handler: + for line in file_handler: + txt_table.append(line) + try: + txt_table.insert(5, txt_table.pop(2)) + with open(txt_file, u"wt", encoding='utf-8') as file_handler: + file_handler.writelines(txt_table) + except IndexError: + pass + + # Generate html table: + hdr_html = [ + u"
".join(row) for row in zip(*header) + ] + _tpc_generate_html_table( + hdr_html, + tbl_lst, + table[u'output-file'], + sort_data=True, + title=table.get(u"title", u""), + generate_rst=False + ) -- cgit 1.2.3-korg