Flutter Engine
The Flutter Engine
sheet.py
Go to the documentation of this file.
1#!/usr/bin/env python
2
3# Copyright 2016 Google Inc.
4#
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7
8from __future__ import print_function
9from _benchresult import BenchResult
10from argparse import ArgumentParser
11from collections import defaultdict, namedtuple
12from datetime import datetime
13import operator
14import os
15import sys
16import tempfile
17import urllib
18import urlparse
19import webbrowser
20
21__argparse = ArgumentParser(description="""
22
23Formats skpbench.py outputs as csv.
24
25This script can also be used to generate a Google sheet:
26
27(1) Install the "Office Editing for Docs, Sheets & Slides" Chrome extension:
28 https://chrome.google.com/webstore/detail/office-editing-for-docs-s/gbkeegbaiigmenfmjfclcdgdpimamgkj
29
30(2) Update your global OS file associations to use Chrome for .csv files.
31
32(3) Run parseskpbench.py with the --open flag.
33
34""")
35
36__argparse.add_argument('-r', '--result',
37 choices=['accum', 'median', 'max', 'min'], default='accum',
38 help="result to use for cell values")
39__argparse.add_argument('-f', '--force',
40 action='store_true', help='silently ignore warnings')
41__argparse.add_argument('-o', '--open',
42 action='store_true',
43 help="generate a temp file and open it (theoretically in a web browser)")
44__argparse.add_argument('-n', '--name',
45 default='skpbench_%s' % datetime.now().strftime('%Y-%m-%d_%H.%M.%S.csv'),
46 help="if using --open, a name for the temp file")
47__argparse.add_argument('sources',
48 nargs='+', help="source files that contain skpbench results ('-' for stdin)")
49
50FLAGS = __argparse.parse_args()
51
52RESULT_QUALIFIERS = ('sample_ms', 'clock', 'metric')
53
54class FullConfig(namedtuple('fullconfig', ('config',) + RESULT_QUALIFIERS)):
55 def qualified_name(self, qualifiers=RESULT_QUALIFIERS):
56 return get_qualified_name(self.config.replace(',', ' '),
57 {x:getattr(self, x) for x in qualifiers})
58
59def get_qualified_name(name, qualifiers):
60 if not qualifiers:
61 return name
62 else:
63 args = ('%s=%s' % (k,v) for k,v in qualifiers.iteritems())
64 return '%s (%s)' % (name, ' '.join(args))
65
66class Parser:
67 def __init__(self):
68 self.sheet_qualifiers = {x:None for x in RESULT_QUALIFIERS}
70 self.fullconfigs = list() # use list to preserve the order.
71 self.rows = defaultdict(dict)
72 self.cols = defaultdict(dict)
73
74 def parse_file(self, infile):
75 for line in infile:
76 match = BenchResult.match(line)
77 if not match:
78 continue
79
80 fullconfig = FullConfig(*(match.get_string(x)
81 for x in FullConfig._fields))
82 if not fullconfig in self.fullconfigs:
83 self.fullconfigs.append(fullconfig)
84
85 for qualifier, value in self.sheet_qualifiers.items():
86 if value is None:
87 self.sheet_qualifiers[qualifier] = match.get_string(qualifier)
88 elif value != match.get_string(qualifier):
89 del self.sheet_qualifiers[qualifier]
90 self.config_qualifiers.add(qualifier)
91
92 self.rows[match.bench][fullconfig] = match.get_string(FLAGS.result)
93 self.cols[fullconfig][match.bench] = getattr(match, FLAGS.result)
94
95 def print_csv(self, outfile=sys.stdout):
96 # Write the title.
97 print(get_qualified_name(FLAGS.result, self.sheet_qualifiers), file=outfile)
98
99 # Write the header.
100 outfile.write('bench,')
101 for fullconfig in self.fullconfigs:
102 outfile.write('%s,' % fullconfig.qualified_name(self.config_qualifiers))
103 outfile.write('\n')
104
105 # Write the rows.
106 for bench, row in self.rows.iteritems():
107 outfile.write('%s,' % bench)
108 for fullconfig in self.fullconfigs:
109 if fullconfig in row:
110 outfile.write('%s,' % row[fullconfig])
111 elif FLAGS.force:
112 outfile.write('NULL,')
113 else:
114 raise ValueError("%s: missing value for %s. (use --force to ignore)" %
115 (bench,
116 fullconfig.qualified_name(self.config_qualifiers)))
117 outfile.write('\n')
118
119 # Add simple, literal averages.
120 if len(self.rows) > 1:
121 outfile.write('\n')
122 self._print_computed_row('MEAN',
123 lambda col: reduce(operator.add, col.values()) / len(col),
124 outfile=outfile)
125 self._print_computed_row('GEOMEAN',
126 lambda col: reduce(operator.mul, col.values()) ** (1.0 / len(col)),
127 outfile=outfile)
128
129 def _print_computed_row(self, name, func, outfile=sys.stdout):
130 outfile.write('%s,' % name)
131 for fullconfig in self.fullconfigs:
132 if len(self.cols[fullconfig]) != len(self.rows):
133 outfile.write('NULL,')
134 continue
135 outfile.write('%.4g,' % func(self.cols[fullconfig]))
136 outfile.write('\n')
137
138def main():
139 parser = Parser()
140
141 # Parse the input files.
142 for src in FLAGS.sources:
143 if src == '-':
144 parser.parse_file(sys.stdin)
145 else:
146 with open(src, mode='r') as infile:
147 parser.parse_file(infile)
148
149 # Print the csv.
150 if not FLAGS.open:
151 parser.print_csv()
152 else:
153 dirname = tempfile.mkdtemp()
154 basename = FLAGS.name
155 if os.path.splitext(basename)[1] != '.csv':
156 basename += '.csv';
157 pathname = os.path.join(dirname, basename)
158 with open(pathname, mode='w') as tmpfile:
159 parser.print_csv(outfile=tmpfile)
160 fileuri = urlparse.urljoin('file:', urllib.pathname2url(pathname))
161 print('opening %s' % fileuri)
162 webbrowser.open(fileuri)
163
164
165if __name__ == '__main__':
166 main()
def qualified_name(self, qualifiers=RESULT_QUALIFIERS)
Definition: sheet.py:55
def _print_computed_row(self, name, func, outfile=sys.stdout)
Definition: sheet.py:129
def print_csv(self, outfile=sys.stdout)
Definition: sheet.py:95
def parse_file(self, infile)
Definition: sheet.py:74
static void append(char **dst, size_t *count, const char *src, size_t n)
Definition: editor.cpp:211
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76
Definition: main.py:1
def print(*args, **kwargs)
Definition: run_tests.py:49
def get_qualified_name(name, qualifiers)
Definition: sheet.py:59
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741