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

Side by Side Diff: tools/callstats.py

Issue 1966193002: Add script injection when replaying with callstats.py (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 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
« no previous file with comments | « src/runtime/runtime-internal.cc ('k') | 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 2016 the V8 project authors. All rights reserved. 2 # Copyright 2016 the V8 project 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 Usage: runtime-call-stats.py [-h] <command> ... 6 Usage: runtime-call-stats.py [-h] <command> ...
7 7
8 Optional arguments: 8 Optional arguments:
9 -h, --help show this help message and exit 9 -h, --help show this help message and exit
10 10
(...skipping 16 matching lines...) Expand all
27 import tempfile 27 import tempfile
28 28
29 import numpy 29 import numpy
30 import scipy 30 import scipy
31 import scipy.stats 31 import scipy.stats
32 from math import sqrt 32 from math import sqrt
33 33
34 34
35 # Run benchmarks. 35 # Run benchmarks.
36 36
37 DEFAULT_SITES = [
38 # top websites (http://alexa.com/topsites): --------------------
39 "https://www.google.de/search?q=v8",
40 "https://www.youtube.com",
41 "https://www.facebook.com/shakira",
42 "http://www.baidu.com/s?wd=v8",
43 "http://www.yahoo.co.jp",
44 "http://www.amazon.com/s/?field-keywords=v8",
45 "http://hi.wikipedia.org/wiki/" \
46 "%E0%A4%AE%E0%A5%81%E0%A4%96%E0%A4%AA%E0%A5%83%E0%A4%B7%E0%A5%8D%E0%A4%A0",
47 "http://www.qq.com",
48 "http://www.twitter.com/taylorswift13",
49 "http://www.reddit.com",
50 "http://www.ebay.fr/sch/i.html?_nkw=v8",
51 "http://edition.cnn.com",
52 "http://world.taobao.com",
53 "http://www.instagram.com/archdigest",
54 "https://www.linkedin.com/pub/dir/?first=john&last=doe&search=search",
55 "http://www.msn.com/ar-ae",
56 "http://www.bing.com/search?q=v8+engine",
57 "http://www.pinterest.com/categories/popular",
58 "http://www.sina.com.cn",
59 "http://weibo.com",
60 "http://yandex.ru/search/?text=v8",
61 # framework driven decisions: -----------------------------------
62 # wikipedia content + angularjs
63 "http://www.wikiwand.com/en/hill",
64 # ember website
65 "http://meta.discourse.org",
66 # backbone js
67 "http://reddit.musicplayer.io",
68 # gwt application
69 "http://inbox.google.com",
70 # webgl / algorithmic case
71 "http://maps.google.co.jp/maps/search/restaurant+tokyo",
72 # whatever framework adwords uses
73 "https://adwords.google.com",
74 ]
75
76
77 def print_command(cmd_args): 37 def print_command(cmd_args):
78 def fix_for_printing(arg): 38 def fix_for_printing(arg):
79 m = re.match(r'^--([^=]+)=(.*)$', arg) 39 m = re.match(r'^--([^=]+)=(.*)$', arg)
80 if m and (' ' in m.group(2) or m.group(2).startswith('-')): 40 if m and (' ' in m.group(2) or m.group(2).startswith('-')):
81 arg = "--{}='{}'".format(m.group(1), m.group(2)) 41 arg = "--{}='{}'".format(m.group(1), m.group(2))
82 elif ' ' in arg: 42 elif ' ' in arg:
83 arg = "'{}'".format(arg) 43 arg = "'{}'".format(arg)
84 return arg 44 return arg
85 print " ".join(map(fix_for_printing, cmd_args)) 45 print " ".join(map(fix_for_printing, cmd_args))
86 46
87 47
88 def start_replay_server(args): 48 def start_replay_server(args, sites):
49 with tempfile.NamedTemporaryFile(prefix='callstats-inject-', suffix='.js',
50 mode='wt', delete=False) as f:
51 injection = f.name
52 generate_injection(f, sites)
89 cmd_args = [ 53 cmd_args = [
90 args.replay_bin, 54 args.replay_bin,
91 "--port=4080", 55 "--port=4080",
92 "--ssl_port=4443", 56 "--ssl_port=4443",
93 "--no-dns_forwarding", 57 "--no-dns_forwarding",
94 "--use_closest_match", 58 "--use_closest_match",
95 "--no-diff_unknown_requests", 59 "--no-diff_unknown_requests",
60 "--inject_scripts=deterministic.js,{}".format(injection),
96 args.replay_wpr, 61 args.replay_wpr,
97 ] 62 ]
98 print "=" * 80 63 print "=" * 80
99 print_command(cmd_args) 64 print_command(cmd_args)
100 with open(os.devnull, 'w') as null: 65 with open(os.devnull, 'w') as null:
101 server = subprocess.Popen(cmd_args, stdout=null, stderr=null) 66 server = subprocess.Popen(cmd_args, stdout=null, stderr=null)
102 print "RUNNING REPLAY SERVER: %s with PID=%s" % (args.replay_bin, server.pid) 67 print "RUNNING REPLAY SERVER: %s with PID=%s" % (args.replay_bin, server.pid)
103 print "=" * 80 68 print "=" * 80
104 return server 69 return {'process': server, 'injection': injection}
105 70
106 71
107 def stop_replay_server(server): 72 def stop_replay_server(server):
108 print("SHUTTING DOWN REPLAY SERVER %s" % server.pid) 73 print("SHUTTING DOWN REPLAY SERVER %s" % server['process'].pid)
109 server.terminate() 74 server['process'].terminate()
75 os.remove(server['injection'])
76
77
78 def generate_injection(f, sites):
79 print >> f, """\
80 (function() {
81 function match(url, item) {
82 if ('regexp' in item) return url.match(item.regexp) !== null;
83 let url_wanted = item.url;
84 // Allow automatic redirections from http to https.
85 if (url_wanted.startsWith("http://") && url.startsWith("https://")) {
86 url_wanted = "https://" + url_wanted.substr(7);
87 }
88 return url.startsWith(url_wanted);
89 };
90
91 function onLoad(e) {
92 let url = e.target.URL;
93 for (let item of sites) {
94 if (!match(url, item)) continue;
95 let timeout = 'timeline' in item ? 2500 * item.timeline + 3000
96 : 'timeout' in item ? 1000 * (item.timeout - 3)
97 : 10000;
98 console.log("Setting time out of " + timeout + " for: " + url);
99 window.setTimeout(function () {
100 console.log("Time is out for: " + url);
101 %GetAndResetRuntimeCallStats(1);
102 }, timeout);
103 return;
104 }
105 console.log("Ignoring: " + url);
106 };
107
108 let sites =
109 """, json.dumps(sites), """;
110
111 console.log("Event listenner added for: " + window.location.href);
112 window.addEventListener("load", onLoad);
113 })();"""
110 114
111 115
112 def run_site(site, domain, args, timeout=None): 116 def run_site(site, domain, args, timeout=None):
113 print "="*80 117 print "="*80
114 print "RUNNING DOMAIN %s" % domain 118 print "RUNNING DOMAIN %s" % domain
115 print "="*80 119 print "="*80
116 result_template = "{domain}#{count}.txt" if args.repeat else "{domain}.txt" 120 result_template = "{domain}#{count}.txt" if args.repeat else "{domain}.txt"
117 count = 0 121 count = 0
122 if timeout is None: timeout = args.timeout
123 if args.replay_wpr: timeout += 1
118 while count == 0 or args.repeat is not None and count < args.repeat: 124 while count == 0 or args.repeat is not None and count < args.repeat:
119 count += 1 125 count += 1
120 result = result_template.format(domain=domain, count=count) 126 result = result_template.format(domain=domain, count=count)
121 retries = 0 127 retries = 0
122 while args.retries is None or retries < args.retries: 128 while args.retries is None or retries < args.retries:
123 retries += 1 129 retries += 1
124 try: 130 try:
125 temp_user_data_dir = args.user_data_dir is None 131 if args.user_data_dir:
126 if temp_user_data_dir: 132 user_data_dir = args.user_data_dir
133 else:
127 user_data_dir = tempfile.mkdtemp(prefix="chr_") 134 user_data_dir = tempfile.mkdtemp(prefix="chr_")
128 js_flags = "--runtime-call-stats" 135 js_flags = "--runtime-call-stats"
136 if args.replay_wpr: js_flags += " --allow-natives-syntax"
129 if args.js_flags: js_flags += " " + args.js_flags 137 if args.js_flags: js_flags += " " + args.js_flags
130 chrome_flags = [ 138 chrome_flags = [
131 "--no-default-browser-check", 139 "--no-default-browser-check",
132 "--disable-translate", 140 "--disable-translate",
133 "--single-process", 141 "--disable-seccomp-sandbox",
134 "--no-sandbox", 142 "--no-sandbox",
135 "--js-flags={}".format(js_flags), 143 "--js-flags={}".format(js_flags),
136 "--no-first-run", 144 "--no-first-run",
137 "--user-data-dir={}".format(user_data_dir), 145 "--user-data-dir={}".format(user_data_dir),
138 ] 146 ]
139 if args.replay_wpr: 147 if args.replay_wpr:
140 chrome_flags += [ 148 chrome_flags += [
141 "--host-resolver-rules=MAP *:80 localhost:4080, " \ 149 "--host-resolver-rules=MAP *:80 localhost:4080, " \
142 "MAP *:443 localhost:4443, " \ 150 "MAP *:443 localhost:4443, " \
143 "EXCLUDE localhost", 151 "EXCLUDE localhost",
144 "--ignore-certificate-errors", 152 "--ignore-certificate-errors",
145 "--disable-web-security", 153 "--disable-web-security",
146 "--reduce-security-for-testing", 154 "--reduce-security-for-testing",
147 "--allow-insecure-localhost", 155 "--allow-insecure-localhost",
148 ] 156 ]
157 else:
158 chrome_flags += [
159 "--single-process",
160 ]
149 if args.chrome_flags: 161 if args.chrome_flags:
150 chrome_flags += args.chrome_flags.split() 162 chrome_flags += args.chrome_flags.split()
151 if timeout is None: timeout = args.timeout
152 cmd_args = [ 163 cmd_args = [
153 "timeout", str(timeout), 164 "timeout", str(timeout),
154 args.with_chrome 165 args.with_chrome
155 ] + chrome_flags + [ site ] 166 ] + chrome_flags + [ site ]
156 print "- " * 40 167 print "- " * 40
157 print_command(cmd_args) 168 print_command(cmd_args)
158 print "- " * 40 169 print "- " * 40
159 with open(result, "wt") as f: 170 with open(result, "wt") as f:
160 status = subprocess.call(cmd_args, stdout=f) 171 status = subprocess.call(cmd_args, stdout=f)
161 # 124 means timeout killed chrome, 0 means the user was bored first! 172 # 124 means timeout killed chrome, 0 means the user was bored first!
162 # If none of these two happened, then chrome apparently crashed, so 173 # If none of these two happened, then chrome apparently crashed, so
163 # it must be called again. 174 # it must be called again.
164 if status != 124 and status != 0: 175 if status != 124 and status != 0:
165 print("CHROME CRASHED, REPEATING RUN"); 176 print("CHROME CRASHED, REPEATING RUN");
166 continue 177 continue
167 # If the stats file is empty, chrome must be called again. 178 # If the stats file is empty, chrome must be called again.
168 if os.path.isfile(result) and os.path.getsize(result) > 0: 179 if os.path.isfile(result) and os.path.getsize(result) > 0:
169 if args.print_url: 180 if args.print_url:
170 with open(result, "at") as f: 181 with open(result, "at") as f:
171 print >> f 182 print >> f
172 print >> f, "URL: {}".format(site) 183 print >> f, "URL: {}".format(site)
173 break 184 break
185 if retries <= 5: timeout += 1
174 print("EMPTY RESULT, REPEATING RUN"); 186 print("EMPTY RESULT, REPEATING RUN");
175 finally: 187 finally:
176 if temp_user_data_dir: 188 if not args.user_data_dir:
177 shutil.rmtree(user_data_dir) 189 shutil.rmtree(user_data_dir)
178 190
179 191
180 def read_sites_file(args): 192 def read_sites_file(args):
181 try: 193 try:
182 sites = [] 194 sites = []
183 try: 195 try:
184 with open(args.sites_file, "rt") as f: 196 with open(args.sites_file, "rt") as f:
185 for item in json.load(f): 197 for item in json.load(f):
186 if 'timeout' not in item: 198 if 'timeout' not in item:
(...skipping 10 matching lines...) Expand all
197 return sites 209 return sites
198 except IOError as e: 210 except IOError as e:
199 args.error("Cannot read from {}. {}.".format(args.sites_file, e.strerror)) 211 args.error("Cannot read from {}. {}.".format(args.sites_file, e.strerror))
200 sys.exit(1) 212 sys.exit(1)
201 213
202 214
203 def do_run(args): 215 def do_run(args):
204 # Determine the websites to benchmark. 216 # Determine the websites to benchmark.
205 if args.sites_file: 217 if args.sites_file:
206 sites = read_sites_file(args) 218 sites = read_sites_file(args)
207 elif args.sites: 219 else:
208 sites = [{'url': site, 'timeout': args.timeout} for site in args.sites] 220 sites = [{'url': site, 'timeout': args.timeout} for site in args.sites]
209 else:
210 sites = [{'url': site, 'timeout': args.timeout} for site in DEFAULT_SITES]
211 # Disambiguate domains, if needed. 221 # Disambiguate domains, if needed.
212 L = [] 222 L = []
213 domains = {} 223 domains = {}
214 for item in sites: 224 for item in sites:
215 site = item['url'] 225 site = item['url']
216 m = re.match(r'^(https?://)?([^/]+)(/.*)?$', site) 226 m = re.match(r'^(https?://)?([^/]+)(/.*)?$', site)
217 if not m: 227 if not m:
218 args.error("Invalid URL {}.".format(site)) 228 args.error("Invalid URL {}.".format(site))
219 continue 229 continue
220 domain = m.group(2) 230 domain = m.group(2)
221 entry = [site, domain, None, item['timeout']] 231 entry = [site, domain, None, item['timeout']]
222 if domain not in domains: 232 if domain not in domains:
223 domains[domain] = entry 233 domains[domain] = entry
224 else: 234 else:
225 if not isinstance(domains[domain], int): 235 if not isinstance(domains[domain], int):
226 domains[domain][2] = 1 236 domains[domain][2] = 1
227 domains[domain] = 1 237 domains[domain] = 1
228 domains[domain] += 1 238 domains[domain] += 1
229 entry[2] = domains[domain] 239 entry[2] = domains[domain]
230 L.append(entry) 240 L.append(entry)
231 if args.replay_wpr: 241 replay_server = start_replay_server(args, sites) if args.replay_wpr else None
232 replay_server = start_replay_server(args);
233 try: 242 try:
234 # Run them. 243 # Run them.
235 for site, domain, count, timeout in L: 244 for site, domain, count, timeout in L:
236 if count is not None: domain = "{}%{}".format(domain, count) 245 if count is not None: domain = "{}%{}".format(domain, count)
237 print site, domain, timeout 246 print site, domain, timeout
238 run_site(site, domain, args, timeout) 247 run_site(site, domain, args, timeout)
239 finally: 248 finally:
240 if replay_server: 249 if replay_server:
241 stop_replay_server(replay_server) 250 stop_replay_server(replay_server)
242 251
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 if args.help_cmd in subparsers: 429 if args.help_cmd in subparsers:
421 subparsers[args.help_cmd].print_help() 430 subparsers[args.help_cmd].print_help()
422 else: 431 else:
423 args.error("Unknown command '{}'".format(args.help_cmd)) 432 args.error("Unknown command '{}'".format(args.help_cmd))
424 else: 433 else:
425 parser.print_help() 434 parser.print_help()
426 435
427 436
428 # Main program, parse command line and execute. 437 # Main program, parse command line and execute.
429 438
439 def coexist(*l):
440 given = sum(1 for x in l if x)
441 return given == 0 or given == len(l)
442
430 def main(): 443 def main():
431 parser = argparse.ArgumentParser() 444 parser = argparse.ArgumentParser()
432 subparser_adder = parser.add_subparsers(title="commands", dest="command", 445 subparser_adder = parser.add_subparsers(title="commands", dest="command",
433 metavar="<command>") 446 metavar="<command>")
434 subparsers = {} 447 subparsers = {}
435 # Command: run. 448 # Command: run.
436 subparsers["run"] = subparser_adder.add_parser( 449 subparsers["run"] = subparser_adder.add_parser(
437 "run", help="run --help") 450 "run", help="run --help")
438 subparsers["run"].set_defaults( 451 subparsers["run"].set_defaults(
439 func=do_run, error=subparsers["run"].error) 452 func=do_run, error=subparsers["run"].error)
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 subparsers["help"] = subparser_adder.add_parser( 517 subparsers["help"] = subparser_adder.add_parser(
505 "help", help="help information") 518 "help", help="help information")
506 subparsers["help"].set_defaults( 519 subparsers["help"].set_defaults(
507 func=lambda args: do_help(parser, subparsers, args), 520 func=lambda args: do_help(parser, subparsers, args),
508 error=subparsers["help"].error) 521 error=subparsers["help"].error)
509 subparsers["help"].add_argument( 522 subparsers["help"].add_argument(
510 "help_cmd", type=str, metavar="<command>", nargs="?", 523 "help_cmd", type=str, metavar="<command>", nargs="?",
511 help="command for which to display help") 524 help="command for which to display help")
512 # Execute the command. 525 # Execute the command.
513 args = parser.parse_args() 526 args = parser.parse_args()
514 if args.command == "run" and args.sites_file and args.sites: 527 setattr(args, 'script_path', os.path.dirname(sys.argv[0]))
515 args.error("if --sites-file is used, no site URLS must be given") 528 if args.command == "run" and coexist(args.sites_file, args.sites):
529 args.error("use either option --sites-file or site URLs")
516 sys.exit(1) 530 sys.exit(1)
517 elif args.command == "run" and args.replay_wpr and not args.replay_bin: 531 elif args.command == "run" and not coexist(args.replay_wpr, args.replay_bin):
518 args.error("if --replay-wpr is used, --replay-bin must be given") 532 args.error("options --replay-wpr and --replay-bin must be used together")
519 sys.exit(1) 533 sys.exit(1)
520 else: 534 else:
521 args.func(args) 535 args.func(args)
522 536
523 if __name__ == "__main__": 537 if __name__ == "__main__":
524 sys.exit(main()) 538 sys.exit(main())
OLDNEW
« no previous file with comments | « src/runtime/runtime-internal.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698