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

Side by Side Diff: bench/bench_graph_svg.py

Issue 12381088: Codes for writing bench data to appengine datastore. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 9 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 ''' 1 '''
2 Created on May 16, 2011 2 Created on May 16, 2011
3 3
4 @author: bungeman 4 @author: bungeman
5 ''' 5 '''
6 import bench_util
7 import getopt
8 import httplib
9 import itertools
10 import json
11 import os
12 import re
6 import sys 13 import sys
7 import getopt 14 import urllib
8 import re 15 import urllib2
9 import os
10 import bench_util
11 import json
12 import xml.sax.saxutils 16 import xml.sax.saxutils
13 17
14 # We throw out any measurement outside this range, and log a warning. 18 # We throw out any measurement outside this range, and log a warning.
15 MIN_REASONABLE_TIME = 0 19 MIN_REASONABLE_TIME = 0
16 MAX_REASONABLE_TIME = 99999 20 MAX_REASONABLE_TIME = 99999
17 21
18 # Constants for prefixes in output title used in buildbot. 22 # Constants for prefixes in output title used in buildbot.
19 TITLE_PREAMBLE = 'Bench_Performance_for_Skia_' 23 TITLE_PREAMBLE = 'Bench_Performance_for_Skia_'
20 TITLE_PREAMBLE_LENGTH = len(TITLE_PREAMBLE) 24 TITLE_PREAMBLE_LENGTH = len(TITLE_PREAMBLE)
21 25
26 # Number of data points to send to appengine at once.
27 DATA_POINT_BATCHSIZE = 100
28
29 def grouper(n, iterable):
30 """Groups list into list of lists for a given size. See itertools doc:
31 http://docs.python.org/2/library/itertools.html#module-itertools
32 """
33 args = [iter(iterable)] * n
34 return [[n for n in t if n] for t in itertools.izip_longest(*args)]
35
36
22 def usage(): 37 def usage():
23 """Prints simple usage information.""" 38 """Prints simple usage information."""
24 39
40 print '-a <url> the url to use for adding bench values to app engine app.'
41 print ' Example: "https://skiadash.appspot.com/add_point".'
42 print ' If not set, will skip this step.'
25 print '-b <bench> the bench to show.' 43 print '-b <bench> the bench to show.'
26 print '-c <config> the config to show (GPU, 8888, 565, etc).' 44 print '-c <config> the config to show (GPU, 8888, 565, etc).'
27 print '-d <dir> a directory containing bench_r<revision>_<scalar> files.' 45 print '-d <dir> a directory containing bench_r<revision>_<scalar> files.'
28 print '-e <file> file containing expected bench values/ranges.' 46 print '-e <file> file containing expected bench values/ranges.'
29 print ' Will raise exception if actual bench values are out of range.' 47 print ' Will raise exception if actual bench values are out of range.'
30 print ' See bench_expectations.txt for data format and examples.' 48 print ' See bench_expectations.txt for data format and examples.'
31 print '-f <revision>[:<revision>] the revisions to use for fitting.' 49 print '-f <revision>[:<revision>] the revisions to use for fitting.'
32 print ' Negative <revision> is taken as offset from most recent revision.' 50 print ' Negative <revision> is taken as offset from most recent revision.'
33 print '-i <time> the time to ignore (w, c, g, etc).' 51 print '-i <time> the time to ignore (w, c, g, etc).'
34 print ' The flag is ignored when -t is set; otherwise we plot all the' 52 print ' The flag is ignored when -t is set; otherwise we plot all the'
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 the operating system's 260-character pathname limit, including chdirs.""" 203 the operating system's 260-character pathname limit, including chdirs."""
186 abs_path = get_abs_path(output_path) 204 abs_path = get_abs_path(output_path)
187 sys.stdout = open(abs_path, 'w') 205 sys.stdout = open(abs_path, 'w')
188 206
189 def create_lines(revision_data_points, settings 207 def create_lines(revision_data_points, settings
190 , bench_of_interest, config_of_interest, time_of_interest 208 , bench_of_interest, config_of_interest, time_of_interest
191 , time_to_ignore): 209 , time_to_ignore):
192 """Convert revision data into a dictionary of line data. 210 """Convert revision data into a dictionary of line data.
193 211
194 ({int:[BenchDataPoints]}, {str:str}, str?, str?, str?) 212 ({int:[BenchDataPoints]}, {str:str}, str?, str?, str?)
195 -> {Label:[(x,y)] | [n].x <= [n+1].x}""" 213 -> {Label:[(x,y)] | [n].x <= [n+1].x}
214 INPUT parameters of the function are:
215 1. a dictionary with integer keys (revision #) and a list of bench data
216 points as values
217 2. a dictionary of setting names to value
218 3-5. optional filter parameters: which bench, config, or timer type is of
219 interest. For each one, if None, process them all.
220 6. optional timer type to ignore
221
222 OUTPUT is a dictionary of this form:
223 keys = Label objects
224 values = a list of (x, y) tuples sorted such that x values increase
225 monotonically
226 """
196 revisions = revision_data_points.keys() 227 revisions = revision_data_points.keys()
197 revisions.sort() 228 revisions.sort()
198 lines = {} # {Label:[(x,y)] | x[n] <= x[n+1]} 229 lines = {} # {Label:[(x,y)] | x[n] <= x[n+1]}
199 for revision in revisions: 230 for revision in revisions:
200 for point in revision_data_points[revision]: 231 for point in revision_data_points[revision]:
201 if (bench_of_interest is not None and 232 if (bench_of_interest is not None and
202 not bench_of_interest == point.bench): 233 not bench_of_interest == point.bench):
203 continue 234 continue
204 235
205 if (config_of_interest is not None and 236 if (config_of_interest is not None and
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 max_up_slope = max(max_up_slope, min_slope) 310 max_up_slope = max(max_up_slope, min_slope)
280 min_down_slope = min(min_down_slope, min_slope) 311 min_down_slope = min(min_down_slope, min_slope)
281 312
282 return (max_up_slope, min_down_slope) 313 return (max_up_slope, min_down_slope)
283 314
284 def main(): 315 def main():
285 """Parses command line and writes output.""" 316 """Parses command line and writes output."""
286 317
287 try: 318 try:
288 opts, _ = getopt.getopt(sys.argv[1:] 319 opts, _ = getopt.getopt(sys.argv[1:]
289 , "b:c:d:e:f:i:l:m:o:r:s:t:x:y:" 320 , "a:b:c:d:e:f:i:l:m:o:r:s:t:x:y:"
290 , "default-setting=") 321 , "default-setting=")
291 except getopt.GetoptError, err: 322 except getopt.GetoptError, err:
292 print str(err) 323 print str(err)
293 usage() 324 usage()
294 sys.exit(2) 325 sys.exit(2)
295 326
296 directory = None 327 directory = None
297 config_of_interest = None 328 config_of_interest = None
298 bench_of_interest = None 329 bench_of_interest = None
299 time_of_interest = None 330 time_of_interest = None
300 time_to_ignore = None 331 time_to_ignore = None
301 bench_expectations = {} 332 bench_expectations = {}
333 appengine_url = None # used for adding data to appengine datastore
302 rep = None # bench representation algorithm 334 rep = None # bench representation algorithm
303 revision_range = '0:' 335 revision_range = '0:'
304 regression_range = '0:' 336 regression_range = '0:'
305 latest_revision = None 337 latest_revision = None
306 requested_height = None 338 requested_height = None
307 requested_width = None 339 requested_width = None
308 title = 'Bench graph' 340 title = 'Bench graph'
309 settings = {} 341 settings = {}
310 default_settings = {} 342 default_settings = {}
311 343
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 # Skip benches without value for latest revision. 395 # Skip benches without value for latest revision.
364 continue 396 continue
365 this_min, this_max = expectations[bench_platform_key] 397 this_min, this_max = expectations[bench_platform_key]
366 if this_bench_value < this_min or this_bench_value > this_max: 398 if this_bench_value < this_min or this_bench_value > this_max:
367 exceptions.append('Bench %s value %s out of range [%s, %s].' % 399 exceptions.append('Bench %s value %s out of range [%s, %s].' %
368 (bench_platform_key, this_bench_value, this_min, this_max)) 400 (bench_platform_key, this_bench_value, this_min, this_max))
369 if exceptions: 401 if exceptions:
370 raise Exception('Bench values out of range:\n' + 402 raise Exception('Bench values out of range:\n' +
371 '\n'.join(exceptions)) 403 '\n'.join(exceptions))
372 404
405 def write_to_appengine(line_data_dict, url, newest_revision, bot):
406 """Writes latest bench values to appengine datastore.
407 line_data_dict: dictionary from create_lines.
408 url: the appengine url used to send bench values to write
409 newest_revision: the latest revision that this script reads
410 bot: the bot platform the bench is run on
411 """
412 data = []
413 for label in line_data_dict:
epoger 2013/03/07 16:56:46 please change this to: for label in line_data_dic
benchen 2013/03/07 17:13:27 Done.
414 if not label.bench.endswith('.skp') or label.time_type:
415 # filter out non-picture and non-walltime benches
416 continue
417 config = label.config
418 rev, val = line_data_dict[label][-1]
epoger 2013/03/07 16:56:46 So I guess the assumption here is that newest_revi
benchen 2013/03/07 17:13:27 Done.
419 if rev != newest_revision:
420 continue
421 data.append({'master': 'Skia', 'bot': bot,
422 'test': config + '/' + label.bench.replace('.skp', ''),
423 'revision': rev, 'value': val, 'error': 0})
424 for curr_data in grouper(DATA_POINT_BATCHSIZE, data):
425 req = urllib2.Request(appengine_url,
426 urllib.urlencode({'data': json.dumps(curr_data)}))
427 try:
428 urllib2.urlopen(req)
429 except urllib2.HTTPError, e:
430 sys.stderr.write("HTTPError for JSON data %s: %s\n" % (
431 data, e))
432 except urllib2.URLError, e:
433 sys.stderr.write("URLError for JSON data %s: %s\n" % (
434 data, e))
435 except httplib.HTTPException, e:
436 sys.stderr.write("HTTPException for JSON data %s: %s\n" % (
437 data, e))
438
373 try: 439 try:
374 for option, value in opts: 440 for option, value in opts:
375 if option == "-b": 441 if option == "-a":
442 appengine_url = value
443 elif option == "-b":
376 bench_of_interest = value 444 bench_of_interest = value
377 elif option == "-c": 445 elif option == "-c":
378 config_of_interest = value 446 config_of_interest = value
379 elif option == "-d": 447 elif option == "-d":
380 directory = value 448 directory = value
381 elif option == "-e": 449 elif option == "-e":
382 read_expectations(bench_expectations, value) 450 read_expectations(bench_expectations, value)
383 elif option == "-f": 451 elif option == "-f":
384 regression_range = value 452 regression_range = value
385 elif option == "-i": 453 elif option == "-i":
(...skipping 28 matching lines...) Expand all
414 sys.exit(2) 482 sys.exit(2)
415 483
416 if time_of_interest: 484 if time_of_interest:
417 time_to_ignore = None 485 time_to_ignore = None
418 486
419 # The title flag (-l) provided in buildbot slave is in the format 487 # The title flag (-l) provided in buildbot slave is in the format
420 # Bench_Performance_for_Skia_<platform>, and we want to extract <platform> 488 # Bench_Performance_for_Skia_<platform>, and we want to extract <platform>
421 # for use in platform_and_alg to track matching benches later. If title flag 489 # for use in platform_and_alg to track matching benches later. If title flag
422 # is not in this format, there may be no matching benches in the file 490 # is not in this format, there may be no matching benches in the file
423 # provided by the expectation_file flag (-e). 491 # provided by the expectation_file flag (-e).
492 bot = title # To store the platform as bot name
424 platform_and_alg = title 493 platform_and_alg = title
425 if platform_and_alg.startswith(TITLE_PREAMBLE): 494 if platform_and_alg.startswith(TITLE_PREAMBLE):
426 platform_and_alg = ( 495 bot = platform_and_alg[TITLE_PREAMBLE_LENGTH:]
427 platform_and_alg[TITLE_PREAMBLE_LENGTH:] + '-' + rep) 496 platform_and_alg = bot + '-' + rep
428 title += ' [representation: %s]' % rep 497 title += ' [representation: %s]' % rep
429 498
430 latest_revision = get_latest_revision(directory) 499 latest_revision = get_latest_revision(directory)
431 oldest_revision, newest_revision = parse_range(revision_range) 500 oldest_revision, newest_revision = parse_range(revision_range)
432 oldest_regression, newest_regression = parse_range(regression_range) 501 oldest_regression, newest_regression = parse_range(regression_range)
433 502
434 unfiltered_revision_data_points = parse_dir(directory 503 unfiltered_revision_data_points = parse_dir(directory
435 , default_settings 504 , default_settings
436 , oldest_revision 505 , oldest_revision
437 , newest_revision 506 , newest_revision
(...skipping 16 matching lines...) Expand all
454 , time_of_interest 523 , time_of_interest
455 , time_to_ignore) 524 , time_to_ignore)
456 525
457 regressions = create_regressions(lines 526 regressions = create_regressions(lines
458 , oldest_regression 527 , oldest_regression
459 , newest_regression) 528 , newest_regression)
460 529
461 output_xhtml(lines, oldest_revision, newest_revision, ignored_revision_data_ points, 530 output_xhtml(lines, oldest_revision, newest_revision, ignored_revision_data_ points,
462 regressions, requested_width, requested_height, title) 531 regressions, requested_width, requested_height, title)
463 532
533 if appengine_url:
534 write_to_appengine(lines, appengine_url, newest_revision, bot)
535
464 check_expectations(lines, bench_expectations, newest_revision, 536 check_expectations(lines, bench_expectations, newest_revision,
465 platform_and_alg) 537 platform_and_alg)
466 538
467 def qa(out): 539 def qa(out):
468 """Stringify input and quote as an xml attribute.""" 540 """Stringify input and quote as an xml attribute."""
469 return xml.sax.saxutils.quoteattr(str(out)) 541 return xml.sax.saxutils.quoteattr(str(out))
470 def qe(out): 542 def qe(out):
471 """Stringify input and escape as xml data.""" 543 """Stringify input and escape as xml data."""
472 return xml.sax.saxutils.escape(str(out)) 544 return xml.sax.saxutils.escape(str(out))
473 545
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 print '<a id="rev_link" xlink:href="" target="_top">' 1027 print '<a id="rev_link" xlink:href="" target="_top">'
956 print '<text id="revision" x="0" y=%s style="' % qa(font_size*2) 1028 print '<text id="revision" x="0" y=%s style="' % qa(font_size*2)
957 print 'font-size: %s; ' % qe(font_size) 1029 print 'font-size: %s; ' % qe(font_size)
958 print 'stroke: #0000dd; text-decoration: underline; ' 1030 print 'stroke: #0000dd; text-decoration: underline; '
959 print '"> </text></a>' 1031 print '"> </text></a>'
960 1032
961 print '</svg>' 1033 print '</svg>'
962 1034
963 if __name__ == "__main__": 1035 if __name__ == "__main__":
964 main() 1036 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