Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: chrome/test/functional/perf/endure_result_parser.py

Issue 10961012: Dump JSON data for stacked graphs in endure_result_parser.py. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Script to parse perf data from Chrome Endure test executions, to be graphed. 6 """Script to parse perf data from Chrome Endure test executions, to be graphed.
7 7
8 This script connects via HTTP to a buildbot master in order to scrape and parse 8 This script connects via HTTP to a buildbot master in order to scrape and parse
9 perf data from Chrome Endure tests that have been run. The perf data is then 9 perf data from Chrome Endure tests that have been run. The perf data is then
10 stored in local text files to be graphed by the Chrome Endure graphing code. 10 stored in local text files to be graphed by the Chrome Endure graphing code.
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 elif int(line_dict['rev']) < int(revision): 111 elif int(line_dict['rev']) < int(revision):
112 break 112 break
113 if not overwritten: 113 if not overwritten:
114 existing_lines.insert(0, simplejson.dumps(new_line)) 114 existing_lines.insert(0, simplejson.dumps(new_line))
115 115
116 with open(data_file, 'w') as f: 116 with open(data_file, 'w') as f:
117 f.write('\n'.join(existing_lines)) 117 f.write('\n'.join(existing_lines))
118 os.chmod(data_file, 0755) 118 os.chmod(data_file, 0755)
119 119
120 120
121 def OutputPerfData(revision, graph_name, values, units, units_x, dest_dir): 121 def OutputPerfData(revision, graph_name, values, units, units_x, dest_dir,
122 is_stacked=False, stack_order=[]):
122 """Outputs perf data to a local text file to be graphed. 123 """Outputs perf data to a local text file to be graphed.
123 124
124 Args: 125 Args:
125 revision: The string revision number associated with the perf data. 126 revision: The string revision number associated with the perf data.
126 graph_name: The string name of the graph on which to plot the data. 127 graph_name: The string name of the graph on which to plot the data.
127 values: A dict which maps a description to a value. A value is either a 128 values: A dict which maps a description to a value. A value is either a
128 single data value to be graphed, or a list of 2-tuples 129 single data value to be graphed, or a list of 2-tuples
129 representing (x, y) points to be graphed for long-running tests. 130 representing (x, y) points to be graphed for long-running tests.
130 units: The string description for the y-axis units on the graph. 131 units: The string description for the y-axis units on the graph.
131 units_x: The string description for the x-axis units on the graph. Should 132 units_x: The string description for the x-axis units on the graph. Should
132 be set to None if the results are not for long-running graphs. 133 be set to None if the results are not for long-running graphs.
133 dest_dir: The name of the destination directory to which to write. 134 dest_dir: The name of the destination directory to which to write.
135 is_stacked: True to draw a "stacked" graph. First-come values are
136 stacked at bottom by default.
137 stack_order: A list that contains order to stack values in the graph.
dennis_jeffrey 2012/09/26 00:58:06 is this an array of perf key strings? If so, mayb
Dai Mikurube (NOT FULLTIME) 2012/09/26 06:11:15 Done.
134 """ 138 """
135 # Update graphs.dat, which contains metadata associated with each graph. 139 # Update graphs.dat, which contains metadata associated with each graph.
136 existing_graphs = [] 140 existing_graphs = []
137 graphs_file = os.path.join(dest_dir, 'graphs.dat') 141 graphs_file = os.path.join(dest_dir, 'graphs.dat')
138 if os.path.exists(graphs_file): 142 if os.path.exists(graphs_file):
139 with open(graphs_file, 'r') as f: 143 with open(graphs_file, 'r') as f:
140 existing_graphs = simplejson.loads(f.read()) 144 existing_graphs = simplejson.loads(f.read())
141 is_new_graph = True 145 is_new_graph = True
142 for graph in existing_graphs: 146 for graph in existing_graphs:
143 if graph['name'] == graph_name: 147 if graph['name'] == graph_name:
(...skipping 28 matching lines...) Expand all
172 points = [] 176 points = []
173 for point in value: 177 for point in value:
174 points.append([str(point[0]), str(point[1])]) 178 points.append([str(point[0]), str(point[1])])
175 new_traces[description] = points 179 new_traces[description] = points
176 else: 180 else:
177 new_traces[description] = [str(value), str(0.0)] 181 new_traces[description] = [str(value), str(0.0)]
178 new_line = { 182 new_line = {
179 'traces': new_traces, 183 'traces': new_traces,
180 'rev': revision 184 'rev': revision
181 } 185 }
186 if is_stacked:
187 new_line['stack'] = is_stacked
dennis_jeffrey 2012/09/26 00:58:06 since we will only include 'stack' in the line if
Dai Mikurube (NOT FULLTIME) 2012/09/26 06:11:15 Done.
188 new_line['stack_order'] = stack_order
182 189
183 WriteToDataFile(new_line, existing_lines, revision, data_file) 190 WriteToDataFile(new_line, existing_lines, revision, data_file)
184 191
185 192
186 def OutputEventData(revision, event_dict, dest_dir): 193 def OutputEventData(revision, event_dict, dest_dir):
187 """Outputs event data to a local text file to be graphed. 194 """Outputs event data to a local text file to be graphed.
188 195
189 Args: 196 Args:
190 revision: The string revision number associated with the event data. 197 revision: The string revision number associated with the event data.
191 event_dict: A dict which maps a description to an array of tuples 198 event_dict: A dict which maps a description to an array of tuples
(...skipping 29 matching lines...) Expand all
221 228
222 Args: 229 Args:
223 revision: The string revision number associated with the new perf entry. 230 revision: The string revision number associated with the new perf entry.
224 content: Fetched stdio data. 231 content: Fetched stdio data.
225 webapp_name: A name of the webapp. 232 webapp_name: A name of the webapp.
226 test_name: A name of the test. 233 test_name: A name of the test.
227 """ 234 """
228 perf_data_raw = [] 235 perf_data_raw = []
229 236
230 def AppendRawPerfData(graph_name, description, value, units, units_x, 237 def AppendRawPerfData(graph_name, description, value, units, units_x,
231 webapp_name, test_name): 238 webapp_name, test_name, is_stacked=False):
232 perf_data_raw.append({ 239 perf_data_raw.append({
233 'graph_name': graph_name, 240 'graph_name': graph_name,
234 'description': description, 241 'description': description,
235 'value': value, 242 'value': value,
236 'units': units, 243 'units': units,
237 'units_x': units_x, 244 'units_x': units_x,
238 'webapp_name': webapp_name, 245 'webapp_name': webapp_name,
239 'test_name': test_name, 246 'test_name': test_name,
247 'stack': is_stacked,
240 }) 248 })
241 249
242 # First scan for short-running perf test results. 250 # First scan for short-running perf test results.
243 for match in re.findall( 251 for match in re.findall(
244 r'RESULT ([^:]+): ([^=]+)= ([-\d\.]+) (\S+)', content): 252 r'RESULT ([^:]+): ([^=]+)= ([-\d\.]+) (\S+)', content):
245 AppendRawPerfData(match[0], match[1], eval(match[2]), match[3], None, 253 AppendRawPerfData(match[0], match[1], eval(match[2]), match[3], None,
246 webapp_name, webapp_name) 254 webapp_name, webapp_name)
247 255
248 # Next scan for long-running perf test results. 256 # Next scan for long-running perf test results.
249 for match in re.findall( 257 for match in re.findall(
250 r'RESULT ([^:]+): ([^=]+)= (\[[^\]]+\]) (\S+) (\S+)', content): 258 r'RESULT ([^:]+): ([^=]+)= (\[[^\]]+\]) (\S+) (\S+)', content):
251 AppendRawPerfData(match[0], match[1], eval(match[2]), match[3], match[4], 259 AppendRawPerfData(match[0], match[1], eval(match[2]), match[3], match[4],
252 webapp_name, test_name) 260 webapp_name, test_name, match[0].endswith('-DMP'))
Dai Mikurube (NOT FULLTIME) 2012/09/20 09:17:30 It's temporary. We need to decide "RESULT" protoc
dennis_jeffrey 2012/09/26 00:58:06 I think this is ok for now, since we append "-DMP"
Dai Mikurube (NOT FULLTIME) 2012/09/26 06:11:15 Done.
253 261
254 # Next scan for events in the test results. 262 # Next scan for events in the test results.
255 for match in re.findall( 263 for match in re.findall(
256 r'RESULT _EVENT_: ([^=]+)= (\[[^\]]+\])', content): 264 r'RESULT _EVENT_: ([^=]+)= (\[[^\]]+\])', content):
257 AppendRawPerfData('_EVENT_', match[0], eval(match[1]), None, None, 265 AppendRawPerfData('_EVENT_', match[0], eval(match[1]), None, None,
258 webapp_name, test_name) 266 webapp_name, test_name)
259 267
260 # For each graph_name/description pair that refers to a long-running test 268 # For each graph_name/description pair that refers to a long-running test
261 # result or an event, concatenate all the results together (assume results 269 # result or an event, concatenate all the results together (assume results
262 # in the input file are in the correct order). For short-running test 270 # in the input file are in the correct order). For short-running test
263 # results, keep just one if more than one is specified. 271 # results, keep just one if more than one is specified.
264 perf_data = {} # Maps a graph-line key to a perf data dictionary. 272 perf_data = {} # Maps a graph-line key to a perf data dictionary.
265 for data in perf_data_raw: 273 for data in perf_data_raw:
266 key1 = data['graph_name'] 274 key1 = data['graph_name']
267 key2 = data['description'] 275 key2 = data['description']
268 if not key1 in perf_data: 276 if not key1 in perf_data:
269 perf_data[key1] = { 277 perf_data[key1] = {
270 'graph_name': data['graph_name'], 278 'graph_name': data['graph_name'],
271 'value': {}, 279 'value': {},
272 'units': data['units'], 280 'units': data['units'],
273 'units_x': data['units_x'], 281 'units_x': data['units_x'],
274 'webapp_name': data['webapp_name'], 282 'webapp_name': data['webapp_name'],
275 'test_name': data['test_name'], 283 'test_name': data['test_name'],
276 } 284 }
285 perf_data[key1]['stack'] = data['stack']
286 if 'stack_order' not in perf_data[key1]:
287 perf_data[key1]['stack_order'] = []
288 if data['description'] not in perf_data[key1]['stack_order']:
289 perf_data[key1]['stack_order'].append(data['description'])
dennis_jeffrey 2012/09/26 00:58:06 should we only execute lines 286-289 if data['stac
Dai Mikurube (NOT FULLTIME) 2012/09/26 06:11:15 I did it to simplify line 321 (calling OutputPerfD
290
277 if data['graph_name'] != '_EVENT_' and not data['units_x']: 291 if data['graph_name'] != '_EVENT_' and not data['units_x']:
278 # Short-running test result. 292 # Short-running test result.
279 perf_data[key1]['value'][key2] = data['value'] 293 perf_data[key1]['value'][key2] = data['value']
280 else: 294 else:
281 # Long-running test result or event. 295 # Long-running test result or event.
282 if key2 in perf_data[key1]['value']: 296 if key2 in perf_data[key1]['value']:
283 perf_data[key1]['value'][key2] += data['value'] 297 perf_data[key1]['value'][key2] += data['value']
284 else: 298 else:
285 perf_data[key1]['value'][key2] = data['value'] 299 perf_data[key1]['value'][key2] = data['value']
286 300
287 # Finally, for each graph-line in |perf_data|, update the associated local 301 # Finally, for each graph-line in |perf_data|, update the associated local
288 # graph data files if necessary. 302 # graph data files if necessary.
289 for perf_data_key in perf_data: 303 for perf_data_key in perf_data:
290 perf_data_dict = perf_data[perf_data_key] 304 perf_data_dict = perf_data[perf_data_key]
291 305
292 dest_dir = os.path.join(LOCAL_GRAPH_DIR, perf_data_dict['webapp_name']) 306 dest_dir = os.path.join(LOCAL_GRAPH_DIR, perf_data_dict['webapp_name'])
293 if not os.path.exists(dest_dir): 307 if not os.path.exists(dest_dir):
294 os.mkdir(dest_dir) # Webapp name directory. 308 os.mkdir(dest_dir) # Webapp name directory.
295 os.chmod(dest_dir, 0755) 309 os.chmod(dest_dir, 0755)
296 dest_dir = os.path.join(dest_dir, perf_data_dict['test_name']) 310 dest_dir = os.path.join(dest_dir, perf_data_dict['test_name'])
297 311
298 SetupBaseGraphDirIfNeeded(perf_data_dict['webapp_name'], 312 SetupBaseGraphDirIfNeeded(perf_data_dict['webapp_name'],
299 perf_data_dict['test_name'], dest_dir) 313 perf_data_dict['test_name'], dest_dir)
300 if perf_data_dict['graph_name'] == '_EVENT_': 314 if perf_data_dict['graph_name'] == '_EVENT_':
301 OutputEventData(revision, perf_data_dict['value'], dest_dir) 315 OutputEventData(revision, perf_data_dict['value'], dest_dir)
302 else: 316 else:
303 OutputPerfData(revision, perf_data_dict['graph_name'], 317 OutputPerfData(revision, perf_data_dict['graph_name'],
304 perf_data_dict['value'], 318 perf_data_dict['value'],
305 perf_data_dict['units'], perf_data_dict['units_x'], 319 perf_data_dict['units'], perf_data_dict['units_x'],
306 dest_dir) 320 dest_dir,
321 perf_data_dict['stack'], perf_data_dict['stack_order'])
307 322
308 323
309 def UpdatePerfDataForSlaveAndBuild(slave_info, build_num): 324 def UpdatePerfDataForSlaveAndBuild(slave_info, build_num):
310 """Process updated perf data for a particular slave and build number. 325 """Process updated perf data for a particular slave and build number.
311 326
312 Args: 327 Args:
313 slave_info: A dictionary containing information about the slave to process. 328 slave_info: A dictionary containing information about the slave to process.
314 build_num: The particular build number on the slave to process. 329 build_num: The particular build number on the slave to process.
315 330
316 Returns: 331 Returns:
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 if not success: 634 if not success:
620 logging.error('Failed to update perf data files.') 635 logging.error('Failed to update perf data files.')
621 sys.exit(0) 636 sys.exit(0)
622 637
623 GenerateIndexPage() 638 GenerateIndexPage()
624 logging.debug('All done!') 639 logging.debug('All done!')
625 640
626 641
627 if __name__ == '__main__': 642 if __name__ == '__main__':
628 main() 643 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698