benchmark_metrics.py revision 77abf01f2cff8bb3a5564f554d9218c085b83d65
1# Copyright 2016 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4"""Computes the metrics for functions, Chrome OS components and benchmarks."""
5
6import collections
7
8
9def ComputeDistanceForFunction(child_functions_statistics_sample,
10                               child_functions_statistics_reference):
11  """Computes the distance metric for a function.
12
13  Args:
14    child_functions_statistics_sample: A dict that has as a key the name of a
15      function and as a value the inclusive count fraction. The keys are
16      the child functions of a sample parent function.
17    child_functions_statistics_reference: A dict that has as a key the name of
18      a function and as a value the inclusive count fraction. The keys are
19      the child functions of a reference parent function.
20  Returns:
21    A float value representing the sum of inclusive count fraction
22    differences of pairs of common child functions. If a child function is
23    present in a single data set, then we consider the missing inclusive
24    count fraction as 0. This value describes the difference in behaviour
25    between a sample and the reference parent function.
26  """
27  # We initialize the distance with a small value to avoid the further
28  # division by zero.
29  distance = 1.0
30
31  for child_function, inclusive_count_fraction_reference in \
32      child_functions_statistics_reference.iteritems():
33    inclusive_count_fraction_sample = 0.0
34
35    if child_function in child_functions_statistics_sample:
36      inclusive_count_fraction_sample = \
37          child_functions_statistics_sample[child_function]
38    distance += \
39        abs(inclusive_count_fraction_sample -
40            inclusive_count_fraction_reference)
41
42  for child_function, inclusive_count_fraction_sample in \
43      child_functions_statistics_sample.iteritems():
44    if child_function not in child_functions_statistics_reference:
45      distance += inclusive_count_fraction_sample
46
47  return distance
48
49
50def ComputeScoreForFunction(distance, reference_fraction, sample_fraction):
51  """Computes the score for a function.
52
53  Args:
54    distance: A float value representing the difference in behaviour between
55      the sample and the reference function.
56    reference_fraction: A float value representing the inclusive count
57      fraction of the reference function.
58    sample_fraction: A float value representing the inclusive count
59      fraction of the sample function.
60  Returns:
61    A float value representing the score of the function.
62  """
63  return reference_fraction * sample_fraction / distance
64
65
66def ComputeMetricsForComponents(cwp_function_groups, function_metrics):
67  """Computes the metrics for a set of Chrome OS components.
68
69  For every Chrome OS group, we compute the number of functions matching the
70  group, the cumulative and average score, the cumulative and average distance
71  of all those functions. A function matches a group if the path of the file
72  containing its definition contains the common path describing the group.
73
74  Args:
75    cwp_function_groups: A dict having as a key the name of the group and as a
76      value a common path describing the group.
77    function_metrics: A dict having as a key the name of the function and the
78      name of the file where it is declared concatenated by a ',', and as a
79      value a tuple containing the distance and the score metrics.
80  Returns:
81    A dict containing as a key the name of the group and as a value a tuple
82    with the group file path, the number of functions matching the group,
83    the cumulative and average score, cumulative and average distance of all
84    those functions.
85  """
86  function_groups_metrics = \
87      collections.defaultdict(lambda : (0, 0.0, 0.0, 0.0, 0.0))
88
89  for function_key, metric in function_metrics.iteritems():
90    function, function_file = function_key.split(',')
91
92    for group, common_path in cwp_function_groups:
93      if common_path not in function_file:
94        continue
95
96      function_distance = metric[0]
97      function_score = metric[1]
98      group_statistic = function_groups_metrics[group]
99
100      function_count = group_statistic[1] + 1
101      function_distance_cum = function_distance + group_statistic[2]
102      function_distance_avg = function_distance_cum / float(function_count)
103      function_score_cum = function_score + group_statistic[4]
104      function_score_avg = function_score_cum / float(function_count)
105
106      function_groups_metrics[group] = \
107          (common_path,
108           function_count,
109           function_distance_cum,
110           function_distance_avg,
111           function_score_cum,
112           function_score_avg)
113      break
114
115  return function_groups_metrics
116
117
118def ComputeMetricsForBenchmark(function_metrics):
119  function_count = len(function_metrics.keys())
120  distance_cum = 0.0
121  distance_avg = 0.0
122  score_cum = 0.0
123  score_avg = 0.0
124
125  for distance, score in function_metrics.values():
126    distance_cum += distance
127    score_cum += score
128
129  distance_avg = distance_cum / float(function_count)
130  score_avg = score_cum / float(function_count)
131  return function_count, distance_cum, distance_avg, score_cum, score_avg
132
133
134def ComputeMetricsForBenchmarkSet(benchmark_set_function_metrics,
135                                  cwp_function_groups):
136  """TODO(evelinad): Add the computation of the metrics for a set of benchmarks.
137  """
138  raise NotImplementedError()
139