| #!/usr/bin/python2 |
| # |
| # Copyright 2016 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Runs an experiment with the benchmark metrics on a pair of CWP data sets. |
| |
| A data set should contain the files with the pairwise inclusive and the |
| inclusive statistics. The pairwise inclusive file contains pairs of |
| parent and child functions with their inclusive count fractions out of the |
| total amount of inclusive count values and the files of the child functions. |
| The inclusive file contains the functions with their inclusive count fraction |
| out of the total amount of inclusive count values and the file name of the |
| function. The input data should be collected using the scripts |
| collect_experiment_data.sh or collect_experiment_data_odd_even_session.sh |
| |
| For every function, this script computes the distance and the score values. |
| The output is stored in the file cwp_functions_statistics_file. |
| |
| For every Chrome OS component, this script computes a set of metrics consisting |
| in the number of functions, the average and cumulative distance and score of |
| the functions matching the group. The output is stored in the file |
| cwp_function_groups_statistics_file. |
| """ |
| |
| import argparse |
| import sys |
| |
| import benchmark_metrics |
| import utils |
| |
| |
| class MetricsExperiment(object): |
| """Runs an experiment with the benchmark metrics on a pair of data sets.""" |
| |
| def __init__(self, cwp_pairwise_inclusive_reference, |
| cwp_pairwise_inclusive_test, cwp_inclusive_reference, |
| cwp_inclusive_test, cwp_function_groups_file, |
| cwp_function_groups_statistics_file, |
| cwp_function_statistics_file): |
| """Initializes the MetricsExperiment class. |
| |
| Args: |
| cwp_pairwise_inclusive_reference: The CSV file containing the pairwise |
| inclusive values from the reference data set. |
| cwp_pairwise_inclusive_test: The CSV file containing the pairwise |
| inclusive values from the test data set. |
| cwp_inclusive_reference: The CSV file containing the inclusive values |
| from the reference data set. |
| cwp_inclusive_test: The CSV file containing the inclusive values from |
| the test data set. |
| cwp_function_groups_file: The CSV file containing the groups of functions. |
| cwp_function_groups_statistics_file: The output CSV file that will |
| contain the metrics for the function groups. |
| cwp_function_statistics_file: The output CSV file that will contain the |
| metrics for the CWP functions. |
| """ |
| self._cwp_pairwise_inclusive_reference = cwp_pairwise_inclusive_reference |
| self._cwp_pairwise_inclusive_test = cwp_pairwise_inclusive_test |
| self._cwp_inclusive_reference = cwp_inclusive_reference |
| self._cwp_inclusive_test = cwp_inclusive_test |
| self._cwp_function_groups_file = cwp_function_groups_file |
| self._cwp_function_groups_statistics_file = \ |
| cwp_function_groups_statistics_file |
| self._cwp_function_statistics_file = cwp_function_statistics_file |
| |
| def PerformComputation(self): |
| """Does the benchmark metrics experimental computation. |
| |
| For every function, it is computed a distance based on the sum of the |
| differences of the fractions spent in the child functions. Afterwards, |
| it is computed a score based on the inclusive values fractions and the |
| distance value. The statistics for all the function are written in the file |
| self._cwp_function_statistics_file. |
| |
| The functions are grouped on Chrome OS components based on the path of the |
| file where a function is defined. For every group, there are computed the |
| total number of functions matching that group, the cumulative distance, the |
| average distance and the cumulative score of the functions. |
| """ |
| |
| inclusive_statistics_reference = \ |
| utils.ParseCWPInclusiveCountFile(self._cwp_inclusive_reference) |
| inclusive_statistics_cum_reference = \ |
| utils.ComputeCWPCummulativeInclusiveStatistics( |
| inclusive_statistics_reference) |
| inclusive_statistics_test = \ |
| utils.ParseCWPInclusiveCountFile(self._cwp_inclusive_test) |
| inclusive_statistics_cum_test = \ |
| utils.ComputeCWPCummulativeInclusiveStatistics( |
| inclusive_statistics_test) |
| pairwise_inclusive_statistics_reference = \ |
| utils.ParseCWPPairwiseInclusiveCountFile( |
| self._cwp_pairwise_inclusive_reference) |
| pairwise_inclusive_fractions_reference = \ |
| utils.ComputeCWPChildFunctionsFractions( |
| inclusive_statistics_cum_reference, |
| pairwise_inclusive_statistics_reference) |
| pairwise_inclusive_statistics_test = \ |
| utils.ParseCWPPairwiseInclusiveCountFile( |
| self._cwp_pairwise_inclusive_test) |
| pairwise_inclusive_fractions_test = \ |
| utils.ComputeCWPChildFunctionsFractions( |
| inclusive_statistics_cum_test, |
| pairwise_inclusive_statistics_test) |
| parent_function_statistics = {} |
| |
| with open(self._cwp_function_groups_file) as input_file: |
| cwp_function_groups = utils.ParseFunctionGroups(input_file.readlines()) |
| |
| for parent_function_key, parent_function_statistics_test \ |
| in inclusive_statistics_test.iteritems(): |
| parent_function_name, _ = parent_function_key.split(',') |
| parent_function_fraction_test = parent_function_statistics_test[2] |
| |
| parent_function_fraction_reference = \ |
| inclusive_statistics_reference[parent_function_key][2] |
| |
| child_functions_fractions_test = \ |
| pairwise_inclusive_fractions_test.get(parent_function_name, {}) |
| |
| child_functions_fractions_reference = \ |
| pairwise_inclusive_fractions_reference.get(parent_function_name, {}) |
| |
| distance = benchmark_metrics.ComputeDistanceForFunction( |
| child_functions_fractions_test, child_functions_fractions_reference) |
| |
| parent_function_score_test = benchmark_metrics.ComputeScoreForFunction( |
| distance, parent_function_fraction_test, |
| parent_function_fraction_reference) |
| |
| parent_function_statistics[parent_function_key] = \ |
| (distance, parent_function_score_test) |
| |
| with open(self._cwp_function_statistics_file, 'w') as output_file: |
| statistics_lines = ['function,file,distance,score'] |
| statistics_lines += \ |
| [','.join([parent_function_key.replace(';;', ','), |
| str(statistic[0]), |
| str(statistic[1])]) |
| for parent_function_key, statistic |
| in parent_function_statistics.iteritems()] |
| output_file.write('\n'.join(statistics_lines)) |
| |
| cwp_groups_statistics_test = benchmark_metrics.ComputeMetricsForComponents( |
| cwp_function_groups, parent_function_statistics) |
| |
| with open(self._cwp_function_groups_statistics_file, 'w') as output_file: |
| group_statistics_lines = \ |
| ['group,file_path,function_count,distance_cum,distance_avg,score_cum,' |
| 'score_avg'] |
| group_statistics_lines += \ |
| [','.join([group_name, |
| str(statistic[0]), |
| str(statistic[1]), |
| str(statistic[2]), |
| str(statistic[3]), |
| str(statistic[4]), |
| str(statistic[5])]) |
| for group_name, statistic |
| in cwp_groups_statistics_test.iteritems()] |
| output_file.write('\n'.join(group_statistics_lines)) |
| |
| |
| def ParseArguments(arguments): |
| parser = argparse.ArgumentParser( |
| description='Runs an experiment with the benchmark metrics on a pair of ' |
| 'CWP data sets.') |
| parser.add_argument( |
| '--cwp_pairwise_inclusive_reference', |
| required=True, |
| help='The reference CSV file that will contain a pair of parent and ' |
| 'child functions with their inclusive count fractions out of the total ' |
| 'amount of inclusive count values.') |
| parser.add_argument( |
| '--cwp_pairwise_inclusive_test', |
| required=True, |
| help='The test CSV file that will contain a pair of parent and ' |
| 'child functions with their inclusive count fractions out of the total ' |
| 'amount of inclusive count values.') |
| parser.add_argument( |
| '--cwp_inclusive_reference', |
| required=True, |
| help='The reference CSV file that will contain a function with its ' |
| 'inclusive count fraction out of the total amount of inclusive count ' |
| 'values.') |
| parser.add_argument( |
| '--cwp_inclusive_test', |
| required=True, |
| help='The test CSV file that will contain a function with its ' |
| 'inclusive count fraction out of the total amount of inclusive count ' |
| 'values.') |
| parser.add_argument( |
| '-g', |
| '--cwp_function_groups_file', |
| required=True, |
| help='The file that will contain the CWP function groups.' |
| 'A line consists in the group name and a file path. A group must ' |
| 'represent a ChromeOS component.') |
| parser.add_argument( |
| '-s', |
| '--cwp_function_groups_statistics_file', |
| required=True, |
| help='The output file that will contain the metric statistics for the ' |
| 'CWP function groups in CSV format. A line consists in the group name, ' |
| 'file path, number of functions matching the group, the total score ' |
| 'and distance values.') |
| parser.add_argument( |
| '-f', |
| '--cwp_function_statistics_file', |
| required=True, |
| help='The output file that will contain the metric statistics for the ' |
| 'CWP functions in CSV format. A line consists in the function name, file ' |
| 'name, cummulative distance, average distance, cummulative score and ' |
| 'average score values.') |
| |
| options = parser.parse_args(arguments) |
| return options |
| |
| |
| def Main(argv): |
| options = ParseArguments(argv) |
| metrics_experiment = MetricsExperiment( |
| options.cwp_pairwise_inclusive_reference, |
| options.cwp_pairwise_inclusive_test, options.cwp_inclusive_reference, |
| options.cwp_inclusive_test, options.cwp_function_groups_file, |
| options.cwp_function_groups_statistics_file, |
| options.cwp_function_statistics_file) |
| metrics_experiment.PerformComputation() |
| |
| |
| if __name__ == '__main__': |
| Main(sys.argv[1:]) |