annotate contrib/compare_two_ftime_report_sets @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 04ced10e8804
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 #!/usr/bin/python
kono
parents:
diff changeset
2
kono
parents:
diff changeset
3 # Script to statistically compare two sets of log files with -ftime-report
kono
parents:
diff changeset
4 # output embedded within them.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 # Contributed by Lawrence Crowl <crowl@google.com>
kono
parents:
diff changeset
7 #
kono
parents:
diff changeset
8 # Copyright (C) 2012 Free Software Foundation, Inc.
kono
parents:
diff changeset
9 #
kono
parents:
diff changeset
10 # This file is part of GCC.
kono
parents:
diff changeset
11 #
kono
parents:
diff changeset
12 # GCC is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
13 # it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
14 # the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
15 # any later version.
kono
parents:
diff changeset
16 #
kono
parents:
diff changeset
17 # GCC is distributed in the hope that it will be useful,
kono
parents:
diff changeset
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
20 # GNU General Public License for more details.
kono
parents:
diff changeset
21 #
kono
parents:
diff changeset
22 # You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
23 # along with GCC; see the file COPYING. If not, write to
kono
parents:
diff changeset
24 # the Free Software Foundation, 51 Franklin Street, Fifth Floor,
kono
parents:
diff changeset
25 # Boston, MA 02110-1301, USA.
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 """ Compare two sets of compile-time performance numbers.
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 The intent of this script is to compare compile-time performance of two
kono
parents:
diff changeset
31 different versions of the compiler. Each version of the compiler must be
kono
parents:
diff changeset
32 run at least three times with the -ftime-report option. Each log file
kono
parents:
diff changeset
33 represents a data point, or trial. The set of trials for each compiler
kono
parents:
diff changeset
34 version constitutes a sample. The ouput of the script is a description
kono
parents:
diff changeset
35 of the statistically significant difference between the two version of
kono
parents:
diff changeset
36 the compiler.
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 The parameters to the script are:
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 Two file patterns that each match a set of log files. You will probably
kono
parents:
diff changeset
41 need to quote the patterns before passing them to the script.
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 Each pattern corresponds to a version of the compiler.
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 A regular expression that finds interesting lines in the log files.
kono
parents:
diff changeset
46 If you want to match the beginning of the line, you will need to add
kono
parents:
diff changeset
47 the ^ operator. The filtering uses Python regular expression syntax.
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 The default is "TOTAL".
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 All of the interesting lines in a single log file are summed to produce
kono
parents:
diff changeset
52 a single trial (data point).
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 A desired statistical confidence within the range 60% to 99.9%. Due to
kono
parents:
diff changeset
55 the implementation, this confidence will be rounded down to one of 60%,
kono
parents:
diff changeset
56 70%, 80%, 90%, 95%, 98%, 99%, 99.5%, 99.8%, and 99.9%.
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 The default is 95.
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 If the computed confidence is lower than desired, the script will
kono
parents:
diff changeset
61 estimate the number of trials needed to meet the desired confidence.
kono
parents:
diff changeset
62 This estimate is not very good, as the variance tends to change as
kono
parents:
diff changeset
63 you increase the number of trials.
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 The most common use of the script is total compile-time comparison between
kono
parents:
diff changeset
66 logfiles stored in different directories.
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 compare_two_ftime_report_sets "Log1/*perf" "Log2/*perf"
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 One can also look at parsing time, but expecting a lower confidence.
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 compare_two_ftime_report_sets "Log1/*perf" "Log2/*perf" "^phase parsing" 75
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 """
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 import os
kono
parents:
diff changeset
78 import sys
kono
parents:
diff changeset
79 import fnmatch
kono
parents:
diff changeset
80 import glob
kono
parents:
diff changeset
81 import re
kono
parents:
diff changeset
82 import math
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 ####################################################################### Utility
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87
kono
parents:
diff changeset
88 def divide(dividend, divisor):
kono
parents:
diff changeset
89 """ Return the quotient, avoiding division by zero.
kono
parents:
diff changeset
90 """
kono
parents:
diff changeset
91 if divisor == 0:
kono
parents:
diff changeset
92 return sys.float_info.max
kono
parents:
diff changeset
93 else:
kono
parents:
diff changeset
94 return dividend / divisor
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 ################################################################# File and Line
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 # Should you repurpose this script, this code might help.
kono
parents:
diff changeset
101 #
kono
parents:
diff changeset
102 #def find_files(topdir, filepat):
kono
parents:
diff changeset
103 # """ Find a set of file names, under a given directory,
kono
parents:
diff changeset
104 # matching a Unix shell file pattern.
kono
parents:
diff changeset
105 # Returns an iterator over the file names.
kono
parents:
diff changeset
106 # """
kono
parents:
diff changeset
107 # for path, dirlist, filelist in os.walk(topdir):
kono
parents:
diff changeset
108 # for name in fnmatch.filter(filelist, filepat):
kono
parents:
diff changeset
109 # yield os.path.join(path, name)
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 def match_files(fileglob):
kono
parents:
diff changeset
113 """ Find a set of file names matching a Unix shell glob pattern.
kono
parents:
diff changeset
114 Returns an iterator over the file names.
kono
parents:
diff changeset
115 """
kono
parents:
diff changeset
116 return glob.iglob(os.path.expanduser(fileglob))
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118
kono
parents:
diff changeset
119 def lines_in_file(filename):
kono
parents:
diff changeset
120 """ Return an iterator over lines in the named file. """
kono
parents:
diff changeset
121 filedesc = open(filename, "r")
kono
parents:
diff changeset
122 for line in filedesc:
kono
parents:
diff changeset
123 yield line
kono
parents:
diff changeset
124 filedesc.close()
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 def lines_containing_pattern(pattern, lines):
kono
parents:
diff changeset
128 """ Find lines by a Python regular-expression.
kono
parents:
diff changeset
129 Returns an iterator over lines containing the expression.
kono
parents:
diff changeset
130 """
kono
parents:
diff changeset
131 parser = re.compile(pattern)
kono
parents:
diff changeset
132 for line in lines:
kono
parents:
diff changeset
133 if parser.search(line):
kono
parents:
diff changeset
134 yield line
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 ############################################################# Number Formatting
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 def strip_redundant_digits(numrep):
kono
parents:
diff changeset
141 if numrep.find(".") == -1:
kono
parents:
diff changeset
142 return numrep
kono
parents:
diff changeset
143 return numrep.rstrip("0").rstrip(".")
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 def text_number(number):
kono
parents:
diff changeset
147 return strip_redundant_digits("%g" % number)
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 def round_significant(digits, number):
kono
parents:
diff changeset
151 if number == 0:
kono
parents:
diff changeset
152 return 0
kono
parents:
diff changeset
153 magnitude = abs(number)
kono
parents:
diff changeset
154 significance = math.floor(math.log10(magnitude))
kono
parents:
diff changeset
155 least_position = int(significance - digits + 1)
kono
parents:
diff changeset
156 return round(number, -least_position)
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 def text_significant(digits, number):
kono
parents:
diff changeset
160 return text_number(round_significant(digits, number))
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 def text_percent(number):
kono
parents:
diff changeset
164 return text_significant(3, number*100) + "%"
kono
parents:
diff changeset
165
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 ################################################################ T-Distribution
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 # This section of code provides functions for using Student's t-distribution.
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 # The functions are implemented using table lookup
kono
parents:
diff changeset
174 # to facilitate implementation of inverse functions.
kono
parents:
diff changeset
175
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 # The table is comprised of row 0 listing the alpha values,
kono
parents:
diff changeset
178 # column 0 listing the degree-of-freedom values,
kono
parents:
diff changeset
179 # and the other entries listing the corresponding t-distribution values.
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 t_dist_table = [
kono
parents:
diff changeset
182 [ 0, 0.200, 0.150, 0.100, 0.050, 0.025, 0.010, 0.005, .0025, 0.001, .0005],
kono
parents:
diff changeset
183 [ 1, 1.376, 1.963, 3.078, 6.314, 12.71, 31.82, 63.66, 127.3, 318.3, 636.6],
kono
parents:
diff changeset
184 [ 2, 1.061, 1.386, 1.886, 2.920, 4.303, 6.965, 9.925, 14.09, 22.33, 31.60],
kono
parents:
diff changeset
185 [ 3, 0.978, 1.250, 1.638, 2.353, 3.182, 4.541, 5.841, 7.453, 10.21, 12.92],
kono
parents:
diff changeset
186 [ 4, 0.941, 1.190, 1.533, 2.132, 2.776, 3.747, 4.604, 5.598, 7.173, 8.610],
kono
parents:
diff changeset
187 [ 5, 0.920, 1.156, 1.476, 2.015, 2.571, 3.365, 4.032, 4.773, 5.894, 6.869],
kono
parents:
diff changeset
188 [ 6, 0.906, 1.134, 1.440, 1.943, 2.447, 3.143, 3.707, 4.317, 5.208, 5.959],
kono
parents:
diff changeset
189 [ 7, 0.896, 1.119, 1.415, 1.895, 2.365, 2.998, 3.499, 4.029, 4.785, 5.408],
kono
parents:
diff changeset
190 [ 8, 0.889, 1.108, 1.397, 1.860, 2.306, 2.896, 3.355, 3.833, 4.501, 5.041],
kono
parents:
diff changeset
191 [ 9, 0.883, 1.100, 1.383, 1.833, 2.262, 2.821, 3.250, 3.690, 4.297, 4.781],
kono
parents:
diff changeset
192 [ 10, 0.879, 1.093, 1.372, 1.812, 2.228, 2.764, 3.169, 3.581, 4.144, 4.587],
kono
parents:
diff changeset
193 [ 11, 0.876, 1.088, 1.363, 1.796, 2.201, 2.718, 3.106, 3.497, 4.025, 4.437],
kono
parents:
diff changeset
194 [ 12, 0.873, 1.083, 1.356, 1.782, 2.179, 2.681, 3.055, 3.428, 3.930, 4.318],
kono
parents:
diff changeset
195 [ 13, 0.870, 1.079, 1.350, 1.771, 2.160, 2.650, 3.012, 3.372, 3.852, 4.221],
kono
parents:
diff changeset
196 [ 14, 0.868, 1.076, 1.345, 1.761, 2.145, 2.624, 2.977, 3.326, 3.787, 4.140],
kono
parents:
diff changeset
197 [ 15, 0.866, 1.074, 1.341, 1.753, 2.131, 2.602, 2.947, 3.286, 3.733, 4.073],
kono
parents:
diff changeset
198 [ 16, 0.865, 1.071, 1.337, 1.746, 2.120, 2.583, 2.921, 3.252, 3.686, 4.015],
kono
parents:
diff changeset
199 [ 17, 0.863, 1.069, 1.333, 1.740, 2.110, 2.567, 2.898, 3.222, 3.646, 3.965],
kono
parents:
diff changeset
200 [ 18, 0.862, 1.067, 1.330, 1.734, 2.101, 2.552, 2.878, 3.197, 3.610, 3.922],
kono
parents:
diff changeset
201 [ 19, 0.861, 1.066, 1.328, 1.729, 2.093, 2.539, 2.861, 3.174, 3.579, 3.883],
kono
parents:
diff changeset
202 [ 20, 0.860, 1.064, 1.325, 1.725, 2.086, 2.528, 2.845, 3.153, 3.552, 3.850],
kono
parents:
diff changeset
203 [ 21, 0.859, 1.063, 1.323, 1.721, 2.080, 2.518, 2.831, 3.135, 3.527, 3.819],
kono
parents:
diff changeset
204 [ 22, 0.858, 1.061, 1.321, 1.717, 2.074, 2.508, 2.819, 3.119, 3.505, 3.792],
kono
parents:
diff changeset
205 [ 23, 0.858, 1.060, 1.319, 1.714, 2.069, 2.500, 2.807, 3.104, 3.485, 3.768],
kono
parents:
diff changeset
206 [ 24, 0.857, 1.059, 1.318, 1.711, 2.064, 2.492, 2.797, 3.091, 3.467, 3.745],
kono
parents:
diff changeset
207 [ 25, 0.856, 1.058, 1.316, 1.708, 2.060, 2.485, 2.787, 3.078, 3.450, 3.725],
kono
parents:
diff changeset
208 [ 26, 0.856, 1.058, 1.315, 1.706, 2.056, 2.479, 2.779, 3.067, 3.435, 3.707],
kono
parents:
diff changeset
209 [ 27, 0.855, 1.057, 1.314, 1.703, 2.052, 2.473, 2.771, 3.057, 3.421, 3.689],
kono
parents:
diff changeset
210 [ 28, 0.855, 1.056, 1.313, 1.701, 2.048, 2.467, 2.763, 3.047, 3.408, 3.674],
kono
parents:
diff changeset
211 [ 29, 0.854, 1.055, 1.311, 1.699, 2.045, 2.462, 2.756, 3.038, 3.396, 3.660],
kono
parents:
diff changeset
212 [ 30, 0.854, 1.055, 1.310, 1.697, 2.042, 2.457, 2.750, 3.030, 3.385, 3.646],
kono
parents:
diff changeset
213 [ 31, 0.853, 1.054, 1.309, 1.696, 2.040, 2.453, 2.744, 3.022, 3.375, 3.633],
kono
parents:
diff changeset
214 [ 32, 0.853, 1.054, 1.309, 1.694, 2.037, 2.449, 2.738, 3.015, 3.365, 3.622],
kono
parents:
diff changeset
215 [ 33, 0.853, 1.053, 1.308, 1.692, 2.035, 2.445, 2.733, 3.008, 3.356, 3.611],
kono
parents:
diff changeset
216 [ 34, 0.852, 1.052, 1.307, 1.691, 2.032, 2.441, 2.728, 3.002, 3.348, 3.601],
kono
parents:
diff changeset
217 [ 35, 0.852, 1.052, 1.306, 1.690, 2.030, 2.438, 2.724, 2.996, 3.340, 3.591],
kono
parents:
diff changeset
218 [ 36, 0.852, 1.052, 1.306, 1.688, 2.028, 2.434, 2.719, 2.990, 3.333, 3.582],
kono
parents:
diff changeset
219 [ 37, 0.851, 1.051, 1.305, 1.687, 2.026, 2.431, 2.715, 2.985, 3.326, 3.574],
kono
parents:
diff changeset
220 [ 38, 0.851, 1.051, 1.304, 1.686, 2.024, 2.429, 2.712, 2.980, 3.319, 3.566],
kono
parents:
diff changeset
221 [ 39, 0.851, 1.050, 1.304, 1.685, 2.023, 2.426, 2.708, 2.976, 3.313, 3.558],
kono
parents:
diff changeset
222 [ 40, 0.851, 1.050, 1.303, 1.684, 2.021, 2.423, 2.704, 2.971, 3.307, 3.551],
kono
parents:
diff changeset
223 [ 50, 0.849, 1.047, 1.299, 1.676, 2.009, 2.403, 2.678, 2.937, 3.261, 3.496],
kono
parents:
diff changeset
224 [ 60, 0.848, 1.045, 1.296, 1.671, 2.000, 2.390, 2.660, 2.915, 3.232, 3.460],
kono
parents:
diff changeset
225 [ 80, 0.846, 1.043, 1.292, 1.664, 1.990, 2.374, 2.639, 2.887, 3.195, 3.416],
kono
parents:
diff changeset
226 [100, 0.845, 1.042, 1.290, 1.660, 1.984, 2.364, 2.626, 2.871, 3.174, 3.390],
kono
parents:
diff changeset
227 [150, 0.844, 1.040, 1.287, 1.655, 1.976, 2.351, 2.609, 2.849, 3.145, 3.357] ]
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 # The functions use the following parameter name conventions:
kono
parents:
diff changeset
231 # alpha - the alpha parameter
kono
parents:
diff changeset
232 # degree - the degree-of-freedom parameter
kono
parents:
diff changeset
233 # value - the t-distribution value for some alpha and degree
kono
parents:
diff changeset
234 # deviations - a confidence interval radius,
kono
parents:
diff changeset
235 # expressed as a multiple of the standard deviation of the sample
kono
parents:
diff changeset
236 # ax - the alpha parameter index
kono
parents:
diff changeset
237 # dx - the degree-of-freedom parameter index
kono
parents:
diff changeset
238
kono
parents:
diff changeset
239 # The interface to this section of code is the last three functions,
kono
parents:
diff changeset
240 # find_t_dist_value, find_t_dist_alpha, and find_t_dist_degree.
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 def t_dist_alpha_at_index(ax):
kono
parents:
diff changeset
244 if ax == 0:
kono
parents:
diff changeset
245 return .25 # effectively no confidence
kono
parents:
diff changeset
246 else:
kono
parents:
diff changeset
247 return t_dist_table[0][ax]
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 def t_dist_degree_at_index(dx):
kono
parents:
diff changeset
251 return t_dist_table[dx][0]
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 def t_dist_value_at_index(ax, dx):
kono
parents:
diff changeset
255 return t_dist_table[dx][ax]
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 def t_dist_index_of_degree(degree):
kono
parents:
diff changeset
259 limit = len(t_dist_table) - 1
kono
parents:
diff changeset
260 dx = 0
kono
parents:
diff changeset
261 while dx < limit and t_dist_degree_at_index(dx+1) <= degree:
kono
parents:
diff changeset
262 dx += 1
kono
parents:
diff changeset
263 return dx
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 def t_dist_index_of_alpha(alpha):
kono
parents:
diff changeset
267 limit = len(t_dist_table[0]) - 1
kono
parents:
diff changeset
268 ax = 0
kono
parents:
diff changeset
269 while ax < limit and t_dist_alpha_at_index(ax+1) >= alpha:
kono
parents:
diff changeset
270 ax += 1
kono
parents:
diff changeset
271 return ax
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 def t_dist_index_of_value(dx, value):
kono
parents:
diff changeset
275 limit = len(t_dist_table[dx]) - 1
kono
parents:
diff changeset
276 ax = 0
kono
parents:
diff changeset
277 while ax < limit and t_dist_value_at_index(ax+1, dx) < value:
kono
parents:
diff changeset
278 ax += 1
kono
parents:
diff changeset
279 return ax
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 def t_dist_value_within_deviations(dx, ax, deviations):
kono
parents:
diff changeset
283 degree = t_dist_degree_at_index(dx)
kono
parents:
diff changeset
284 count = degree + 1
kono
parents:
diff changeset
285 root = math.sqrt(count)
kono
parents:
diff changeset
286 value = t_dist_value_at_index(ax, dx)
kono
parents:
diff changeset
287 nominal = value / root
kono
parents:
diff changeset
288 comparison = nominal <= deviations
kono
parents:
diff changeset
289 return comparison
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 def t_dist_index_of_degree_for_deviations(ax, deviations):
kono
parents:
diff changeset
293 limit = len(t_dist_table) - 1
kono
parents:
diff changeset
294 dx = 1
kono
parents:
diff changeset
295 while dx < limit and not t_dist_value_within_deviations(dx, ax, deviations):
kono
parents:
diff changeset
296 dx += 1
kono
parents:
diff changeset
297 return dx
kono
parents:
diff changeset
298
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 def find_t_dist_value(alpha, degree):
kono
parents:
diff changeset
301 """ Return the t-distribution value.
kono
parents:
diff changeset
302 The parameters are alpha and degree of freedom.
kono
parents:
diff changeset
303 """
kono
parents:
diff changeset
304 dx = t_dist_index_of_degree(degree)
kono
parents:
diff changeset
305 ax = t_dist_index_of_alpha(alpha)
kono
parents:
diff changeset
306 return t_dist_value_at_index(ax, dx)
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308
kono
parents:
diff changeset
309 def find_t_dist_alpha(value, degree):
kono
parents:
diff changeset
310 """ Return the alpha.
kono
parents:
diff changeset
311 The parameters are the t-distribution value for a given degree of freedom.
kono
parents:
diff changeset
312 """
kono
parents:
diff changeset
313 dx = t_dist_index_of_degree(degree)
kono
parents:
diff changeset
314 ax = t_dist_index_of_value(dx, value)
kono
parents:
diff changeset
315 return t_dist_alpha_at_index(ax)
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 def find_t_dist_degree(alpha, deviations):
kono
parents:
diff changeset
319 """ Return the degree-of-freedom.
kono
parents:
diff changeset
320 The parameters are the desired alpha and the number of standard deviations
kono
parents:
diff changeset
321 away from the mean that the degree should handle.
kono
parents:
diff changeset
322 """
kono
parents:
diff changeset
323 ax = t_dist_index_of_alpha(alpha)
kono
parents:
diff changeset
324 dx = t_dist_index_of_degree_for_deviations(ax, deviations)
kono
parents:
diff changeset
325 return t_dist_degree_at_index(dx)
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 ############################################################## Core Statistical
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330
kono
parents:
diff changeset
331 # This section provides the core statistical classes and functions.
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 class Accumulator:
kono
parents:
diff changeset
335
kono
parents:
diff changeset
336 """ An accumulator for statistical information using arithmetic mean. """
kono
parents:
diff changeset
337
kono
parents:
diff changeset
338 def __init__(self):
kono
parents:
diff changeset
339 self.count = 0
kono
parents:
diff changeset
340 self.mean = 0
kono
parents:
diff changeset
341 self.sumsqdiff = 0
kono
parents:
diff changeset
342
kono
parents:
diff changeset
343 def insert(self, value):
kono
parents:
diff changeset
344 self.count += 1
kono
parents:
diff changeset
345 diff = value - self.mean
kono
parents:
diff changeset
346 self.mean += diff / self.count
kono
parents:
diff changeset
347 self.sumsqdiff += (self.count - 1) * diff * diff / self.count
kono
parents:
diff changeset
348
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 def fill_accumulator_from_values(values):
kono
parents:
diff changeset
351 accumulator = Accumulator()
kono
parents:
diff changeset
352 for value in values:
kono
parents:
diff changeset
353 accumulator.insert(value)
kono
parents:
diff changeset
354 return accumulator
kono
parents:
diff changeset
355
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 def alpha_from_confidence(confidence):
kono
parents:
diff changeset
358 scrubbed = min(99.99, max(confidence, 60))
kono
parents:
diff changeset
359 return (100.0 - scrubbed) / 200.0
kono
parents:
diff changeset
360
kono
parents:
diff changeset
361
kono
parents:
diff changeset
362 def confidence_from_alpha(alpha):
kono
parents:
diff changeset
363 return 100 - 200 * alpha
kono
parents:
diff changeset
364
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 class Sample:
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 """ A description of a sample using an arithmetic mean. """
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 def __init__(self, accumulator, alpha):
kono
parents:
diff changeset
371 if accumulator.count < 3:
kono
parents:
diff changeset
372 sys.exit("Samples must contain three trials.")
kono
parents:
diff changeset
373 self.count = accumulator.count
kono
parents:
diff changeset
374 self.mean = accumulator.mean
kono
parents:
diff changeset
375 variance = accumulator.sumsqdiff / (self.count - 1)
kono
parents:
diff changeset
376 self.deviation = math.sqrt(variance)
kono
parents:
diff changeset
377 self.error = self.deviation / math.sqrt(self.count)
kono
parents:
diff changeset
378 self.alpha = alpha
kono
parents:
diff changeset
379 self.radius = find_t_dist_value(alpha, self.count - 1) * self.error
kono
parents:
diff changeset
380
kono
parents:
diff changeset
381 def alpha_for_radius(self, radius):
kono
parents:
diff changeset
382 return find_t_dist_alpha(divide(radius, self.error), self.count)
kono
parents:
diff changeset
383
kono
parents:
diff changeset
384 def degree_for_radius(self, radius):
kono
parents:
diff changeset
385 return find_t_dist_degree(self.alpha, divide(radius, self.deviation))
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 def __str__(self):
kono
parents:
diff changeset
388 text = "trial count is " + text_number(self.count)
kono
parents:
diff changeset
389 text += ", mean is " + text_number(self.mean)
kono
parents:
diff changeset
390 text += " (" + text_number(confidence_from_alpha(self.alpha)) +"%"
kono
parents:
diff changeset
391 text += " confidence in " + text_number(self.mean - self.radius)
kono
parents:
diff changeset
392 text += " to " + text_number(self.mean + self.radius) + ")"
kono
parents:
diff changeset
393 text += ",\nstd.deviation is " + text_number(self.deviation)
kono
parents:
diff changeset
394 text += ", std.error is " + text_number(self.error)
kono
parents:
diff changeset
395 return text
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 def sample_from_values(values, alpha):
kono
parents:
diff changeset
399 accumulator = fill_accumulator_from_values(values)
kono
parents:
diff changeset
400 return Sample(accumulator, alpha)
kono
parents:
diff changeset
401
kono
parents:
diff changeset
402
kono
parents:
diff changeset
403 class Comparison:
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 """ A comparison of two samples using arithmetic means. """
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 def __init__(self, first, second, alpha):
kono
parents:
diff changeset
408 if first.mean > second.mean:
kono
parents:
diff changeset
409 self.upper = first
kono
parents:
diff changeset
410 self.lower = second
kono
parents:
diff changeset
411 self.larger = "first"
kono
parents:
diff changeset
412 else:
kono
parents:
diff changeset
413 self.upper = second
kono
parents:
diff changeset
414 self.lower = first
kono
parents:
diff changeset
415 self.larger = "second"
kono
parents:
diff changeset
416 self.a_wanted = alpha
kono
parents:
diff changeset
417 radius = self.upper.mean - self.lower.mean
kono
parents:
diff changeset
418 rising = self.lower.alpha_for_radius(radius)
kono
parents:
diff changeset
419 falling = self.upper.alpha_for_radius(radius)
kono
parents:
diff changeset
420 self.a_actual = max(rising, falling)
kono
parents:
diff changeset
421 rising = self.lower.degree_for_radius(radius)
kono
parents:
diff changeset
422 falling = self.upper.degree_for_radius(radius)
kono
parents:
diff changeset
423 self.count = max(rising, falling) + 1
kono
parents:
diff changeset
424
kono
parents:
diff changeset
425 def __str__(self):
kono
parents:
diff changeset
426 message = "The " + self.larger + " sample appears to be "
kono
parents:
diff changeset
427 change = divide(self.upper.mean, self.lower.mean) - 1
kono
parents:
diff changeset
428 message += text_percent(change) + " larger,\n"
kono
parents:
diff changeset
429 confidence = confidence_from_alpha(self.a_actual)
kono
parents:
diff changeset
430 if confidence >= 60:
kono
parents:
diff changeset
431 message += "with " + text_number(confidence) + "% confidence"
kono
parents:
diff changeset
432 message += " of being larger."
kono
parents:
diff changeset
433 else:
kono
parents:
diff changeset
434 message += "but with no confidence of actually being larger."
kono
parents:
diff changeset
435 if self.a_actual > self.a_wanted:
kono
parents:
diff changeset
436 confidence = confidence_from_alpha(self.a_wanted)
kono
parents:
diff changeset
437 message += "\nTo reach " + text_number(confidence) + "% confidence,"
kono
parents:
diff changeset
438 if self.count < 100:
kono
parents:
diff changeset
439 message += " you need roughly " + text_number(self.count) + " trials,\n"
kono
parents:
diff changeset
440 message += "assuming the standard deviation is stable, which is iffy."
kono
parents:
diff changeset
441 else:
kono
parents:
diff changeset
442 message += "\nyou need to reduce the larger deviation"
kono
parents:
diff changeset
443 message += " or increase the number of trials."
kono
parents:
diff changeset
444 return message
kono
parents:
diff changeset
445
kono
parents:
diff changeset
446
kono
parents:
diff changeset
447 ############################################################ Single Value Files
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 # This section provides functions to compare two raw data files,
kono
parents:
diff changeset
451 # each containing a whole sample consisting of single number per line.
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 # Should you repurpose this script, this code might help.
kono
parents:
diff changeset
455 #
kono
parents:
diff changeset
456 #def values_from_data_file(filename):
kono
parents:
diff changeset
457 # for line in lines_in_file(filename):
kono
parents:
diff changeset
458 # yield float(line)
kono
parents:
diff changeset
459
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 # Should you repurpose this script, this code might help.
kono
parents:
diff changeset
462 #
kono
parents:
diff changeset
463 #def sample_from_data_file(filename, alpha):
kono
parents:
diff changeset
464 # confidence = confidence_from_alpha(alpha)
kono
parents:
diff changeset
465 # text = "\nArithmetic sample for data file\n\"" + filename + "\""
kono
parents:
diff changeset
466 # text += " with desired confidence " + text_number(confidence) + " is "
kono
parents:
diff changeset
467 # print text
kono
parents:
diff changeset
468 # values = values_from_data_file(filename)
kono
parents:
diff changeset
469 # sample = sample_from_values(values, alpha)
kono
parents:
diff changeset
470 # print sample
kono
parents:
diff changeset
471 # return sample
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 # Should you repurpose this script, this code might help.
kono
parents:
diff changeset
475 #
kono
parents:
diff changeset
476 #def compare_two_data_files(filename1, filename2, confidence):
kono
parents:
diff changeset
477 # alpha = alpha_from_confidence(confidence)
kono
parents:
diff changeset
478 # sample1 = sample_from_data_file(filename1, alpha)
kono
parents:
diff changeset
479 # sample2 = sample_from_data_file(filename2, alpha)
kono
parents:
diff changeset
480 # print
kono
parents:
diff changeset
481 # print Comparison(sample1, sample2, alpha)
kono
parents:
diff changeset
482
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 # Should you repurpose this script, this code might help.
kono
parents:
diff changeset
485 #
kono
parents:
diff changeset
486 #def command_two_data_files():
kono
parents:
diff changeset
487 # argc = len(sys.argv)
kono
parents:
diff changeset
488 # if argc < 2 or 4 < argc:
kono
parents:
diff changeset
489 # message = "usage: " + sys.argv[0]
kono
parents:
diff changeset
490 # message += " file-name file-name [confidence]"
kono
parents:
diff changeset
491 # print message
kono
parents:
diff changeset
492 # else:
kono
parents:
diff changeset
493 # filename1 = sys.argv[1]
kono
parents:
diff changeset
494 # filename2 = sys.argv[2]
kono
parents:
diff changeset
495 # if len(sys.argv) >= 4:
kono
parents:
diff changeset
496 # confidence = int(sys.argv[3])
kono
parents:
diff changeset
497 # else:
kono
parents:
diff changeset
498 # confidence = 95
kono
parents:
diff changeset
499 # compare_two_data_files(filename1, filename2, confidence)
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501
kono
parents:
diff changeset
502 ############################################### -ftime-report TimeVar Log Files
kono
parents:
diff changeset
503
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 # This section provides functions to compare two sets of -ftime-report log
kono
parents:
diff changeset
506 # files. Each set is a sample, where each data point is derived from the
kono
parents:
diff changeset
507 # sum of values in a single log file.
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 label = r"^ *([^:]*[^: ]) *:"
kono
parents:
diff changeset
511 number = r" *([0-9.]*) *"
kono
parents:
diff changeset
512 percent = r"\( *[0-9]*\%\)"
kono
parents:
diff changeset
513 numpct = number + percent
kono
parents:
diff changeset
514 total_format = label + number + number + number + number + " kB\n"
kono
parents:
diff changeset
515 total_parser = re.compile(total_format)
kono
parents:
diff changeset
516 tmvar_format = label + numpct + " usr" + numpct + " sys"
kono
parents:
diff changeset
517 tmvar_format += numpct + " wall" + number + " kB " + percent + " ggc\n"
kono
parents:
diff changeset
518 tmvar_parser = re.compile(tmvar_format)
kono
parents:
diff changeset
519 replace = r"\2\t\3\t\4\t\5\t\1"
kono
parents:
diff changeset
520
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 def split_time_report(lines, pattern):
kono
parents:
diff changeset
523 if pattern == "TOTAL":
kono
parents:
diff changeset
524 parser = total_parser
kono
parents:
diff changeset
525 else:
kono
parents:
diff changeset
526 parser = tmvar_parser
kono
parents:
diff changeset
527 for line in lines:
kono
parents:
diff changeset
528 modified = parser.sub(replace, line)
kono
parents:
diff changeset
529 if modified != line:
kono
parents:
diff changeset
530 yield re.split("\t", modified)
kono
parents:
diff changeset
531
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 def extract_cpu_time(tvtuples):
kono
parents:
diff changeset
534 for tuple in tvtuples:
kono
parents:
diff changeset
535 yield float(tuple[0]) + float(tuple[1])
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 def sum_values(values):
kono
parents:
diff changeset
539 sum = 0
kono
parents:
diff changeset
540 for value in values:
kono
parents:
diff changeset
541 sum += value
kono
parents:
diff changeset
542 return sum
kono
parents:
diff changeset
543
kono
parents:
diff changeset
544
kono
parents:
diff changeset
545 def extract_time_for_timevar_log(filename, pattern):
kono
parents:
diff changeset
546 lines = lines_in_file(filename)
kono
parents:
diff changeset
547 tmvars = lines_containing_pattern(pattern, lines)
kono
parents:
diff changeset
548 tuples = split_time_report(tmvars, pattern)
kono
parents:
diff changeset
549 times = extract_cpu_time(tuples)
kono
parents:
diff changeset
550 return sum_values(times)
kono
parents:
diff changeset
551
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 def extract_times_for_timevar_logs(filelist, pattern):
kono
parents:
diff changeset
554 for filename in filelist:
kono
parents:
diff changeset
555 yield extract_time_for_timevar_log(filename, pattern)
kono
parents:
diff changeset
556
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 def sample_from_timevar_logs(fileglob, pattern, alpha):
kono
parents:
diff changeset
559 confidence = confidence_from_alpha(alpha)
kono
parents:
diff changeset
560 text = "\nArithmetic sample for timevar log files\n\"" + fileglob + "\""
kono
parents:
diff changeset
561 text += "\nand selecting lines containing \"" + pattern + "\""
kono
parents:
diff changeset
562 text += " with desired confidence " + text_number(confidence) + " is "
kono
parents:
diff changeset
563 print text
kono
parents:
diff changeset
564 filelist = match_files(fileglob)
kono
parents:
diff changeset
565 values = extract_times_for_timevar_logs(filelist, pattern)
kono
parents:
diff changeset
566 sample = sample_from_values(values, alpha)
kono
parents:
diff changeset
567 print sample
kono
parents:
diff changeset
568 return sample
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570
kono
parents:
diff changeset
571 def compare_two_timevar_logs(fileglob1, fileglob2, pattern, confidence):
kono
parents:
diff changeset
572 alpha = alpha_from_confidence(confidence)
kono
parents:
diff changeset
573 sample1 = sample_from_timevar_logs(fileglob1, pattern, alpha)
kono
parents:
diff changeset
574 sample2 = sample_from_timevar_logs(fileglob2, pattern, alpha)
kono
parents:
diff changeset
575 print
kono
parents:
diff changeset
576 print Comparison(sample1, sample2, alpha)
kono
parents:
diff changeset
577
kono
parents:
diff changeset
578
kono
parents:
diff changeset
579 def command_two_timevar_logs():
kono
parents:
diff changeset
580 argc = len(sys.argv)
kono
parents:
diff changeset
581 if argc < 3 or 5 < argc:
kono
parents:
diff changeset
582 message = "usage: " + sys.argv[0]
kono
parents:
diff changeset
583 message += " file-pattern file-pattern [line-pattern [confidence]]"
kono
parents:
diff changeset
584 print message
kono
parents:
diff changeset
585 else:
kono
parents:
diff changeset
586 filepat1 = sys.argv[1]
kono
parents:
diff changeset
587 filepat2 = sys.argv[2]
kono
parents:
diff changeset
588 if len(sys.argv) >= 5:
kono
parents:
diff changeset
589 confidence = int(sys.argv[4])
kono
parents:
diff changeset
590 else:
kono
parents:
diff changeset
591 confidence = 95
kono
parents:
diff changeset
592 if len(sys.argv) >= 4:
kono
parents:
diff changeset
593 linepat = sys.argv[3]
kono
parents:
diff changeset
594 else:
kono
parents:
diff changeset
595 linepat = "TOTAL"
kono
parents:
diff changeset
596 compare_two_timevar_logs(filepat1, filepat2, linepat, confidence)
kono
parents:
diff changeset
597
kono
parents:
diff changeset
598
kono
parents:
diff changeset
599 ########################################################################## Main
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601
kono
parents:
diff changeset
602 # This section is the main code, implementing the command.
kono
parents:
diff changeset
603
kono
parents:
diff changeset
604
kono
parents:
diff changeset
605 command_two_timevar_logs()