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

Side by Side Diff: tools/callstats.py

Issue 1967123002: Add callstats.py run --refresh flag (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 elif ' ' in arg: 42 elif ' ' in arg:
43 arg = "'{}'".format(arg) 43 arg = "'{}'".format(arg)
44 return arg 44 return arg
45 print " ".join(map(fix_for_printing, cmd_args)) 45 print " ".join(map(fix_for_printing, cmd_args))
46 46
47 47
48 def start_replay_server(args, sites): 48 def start_replay_server(args, sites):
49 with tempfile.NamedTemporaryFile(prefix='callstats-inject-', suffix='.js', 49 with tempfile.NamedTemporaryFile(prefix='callstats-inject-', suffix='.js',
50 mode='wt', delete=False) as f: 50 mode='wt', delete=False) as f:
51 injection = f.name 51 injection = f.name
52 generate_injection(f, sites) 52 generate_injection(f, sites, args.refresh)
53 cmd_args = [ 53 cmd_args = [
54 args.replay_bin, 54 args.replay_bin,
55 "--port=4080", 55 "--port=4080",
56 "--ssl_port=4443", 56 "--ssl_port=4443",
57 "--no-dns_forwarding", 57 "--no-dns_forwarding",
58 "--use_closest_match", 58 "--use_closest_match",
59 "--no-diff_unknown_requests", 59 "--no-diff_unknown_requests",
60 "--inject_scripts=deterministic.js,{}".format(injection), 60 "--inject_scripts=deterministic.js,{}".format(injection),
61 args.replay_wpr, 61 args.replay_wpr,
62 ] 62 ]
63 print "=" * 80 63 print "=" * 80
64 print_command(cmd_args) 64 print_command(cmd_args)
65 with open(os.devnull, 'w') as null: 65 with open(os.devnull, 'w') as null:
66 server = subprocess.Popen(cmd_args, stdout=null, stderr=null) 66 server = subprocess.Popen(cmd_args, stdout=null, stderr=null)
67 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)
68 print "=" * 80 68 print "=" * 80
69 return {'process': server, 'injection': injection} 69 return {'process': server, 'injection': injection}
70 70
71 71
72 def stop_replay_server(server): 72 def stop_replay_server(server):
73 print("SHUTTING DOWN REPLAY SERVER %s" % server['process'].pid) 73 print("SHUTTING DOWN REPLAY SERVER %s" % server['process'].pid)
74 server['process'].terminate() 74 server['process'].terminate()
75 os.remove(server['injection']) 75 os.remove(server['injection'])
76 76
77 77
78 def generate_injection(f, sites): 78 def generate_injection(f, sites, refreshes=0):
79 print >> f, """\ 79 print >> f, """\
80 (function() { 80 (function() {
81 let s = window.sessionStorage.getItem("refreshCounter");
82 let refreshTotal = """, refreshes, """;
83 let refreshCounter = s ? parseInt(s) : refreshTotal;
84 let refreshId = refreshTotal - refreshCounter;
85 if (refreshCounter > 0) {
86 window.sessionStorage.setItem("refreshCounter", refreshCounter-1);
87 }
88
81 function match(url, item) { 89 function match(url, item) {
82 if ('regexp' in item) return url.match(item.regexp) !== null; 90 if ('regexp' in item) return url.match(item.regexp) !== null;
83 let url_wanted = item.url; 91 let url_wanted = item.url;
84 // Allow automatic redirections from http to https. 92 // Allow automatic redirections from http to https.
85 if (url_wanted.startsWith("http://") && url.startsWith("https://")) { 93 if (url_wanted.startsWith("http://") && url.startsWith("https://")) {
86 url_wanted = "https://" + url_wanted.substr(7); 94 url_wanted = "https://" + url_wanted.substr(7);
87 } 95 }
88 return url.startsWith(url_wanted); 96 return url.startsWith(url_wanted);
89 }; 97 };
90 98
91 function onLoad(e) { 99 function onLoad(e) {
92 let url = e.target.URL; 100 let url = e.target.URL;
93 for (let item of sites) { 101 for (let item of sites) {
94 if (!match(url, item)) continue; 102 if (!match(url, item)) continue;
95 let timeout = 'timeline' in item ? 2500 * item.timeline + 3000 103 let timeout = 'timeline' in item ? 2500 * item.timeline
96 : 'timeout' in item ? 1000 * (item.timeout - 3) 104 : 'timeout' in item ? 1000 * (item.timeout - 3)
97 : 10000; 105 : 10000;
98 console.log("Setting time out of " + timeout + " for: " + url); 106 console.log("Setting time out of " + timeout + " for: " + url);
99 window.setTimeout(function () { 107 window.setTimeout(function() {
100 console.log("Time is out for: " + url); 108 console.log("Time is out for: " + url);
101 %GetAndResetRuntimeCallStats(1); 109 let msg = "STATS: (" + refreshId + ") " + url;
110 %GetAndResetRuntimeCallStats(1, msg);
111 if (refreshCounter > 0) {
112 console.log("Refresh counter is " + refreshCounter + ", refreshing: " + url);
113 window.location.reload();
114 }
102 }, timeout); 115 }, timeout);
103 return; 116 return;
104 } 117 }
105 console.log("Ignoring: " + url); 118 console.log("Ignoring: " + url);
106 }; 119 };
107 120
108 let sites = 121 let sites =
109 """, json.dumps(sites), """; 122 """, json.dumps(sites), """;
110 123
111 console.log("Event listenner added for: " + window.location.href); 124 console.log("Event listenner added for: " + window.location.href);
112 window.addEventListener("load", onLoad); 125 window.addEventListener("load", onLoad);
113 })();""" 126 })();"""
114 127
115 128
116 def run_site(site, domain, args, timeout=None): 129 def run_site(site, domain, args, timeout=None):
117 print "="*80 130 print "="*80
118 print "RUNNING DOMAIN %s" % domain 131 print "RUNNING DOMAIN %s" % domain
119 print "="*80 132 print "="*80
120 result_template = "{domain}#{count}.txt" if args.repeat else "{domain}.txt" 133 result_template = "{domain}#{count}.txt" if args.repeat else "{domain}.txt"
121 count = 0 134 count = 0
122 if timeout is None: timeout = args.timeout 135 if timeout is None: timeout = args.timeout
123 if args.replay_wpr: timeout += 1 136 if args.replay_wpr:
137 timeout *= 1 + args.refresh
138 timeout += 1
124 while count == 0 or args.repeat is not None and count < args.repeat: 139 while count == 0 or args.repeat is not None and count < args.repeat:
125 count += 1 140 count += 1
126 result = result_template.format(domain=domain, count=count) 141 result = result_template.format(domain=domain, count=count)
127 retries = 0 142 retries = 0
128 while args.retries is None or retries < args.retries: 143 while args.retries is None or retries < args.retries:
129 retries += 1 144 retries += 1
130 try: 145 try:
131 if args.user_data_dir: 146 if args.user_data_dir:
132 user_data_dir = args.user_data_dir 147 user_data_dir = args.user_data_dir
133 else: 148 else:
134 user_data_dir = tempfile.mkdtemp(prefix="chr_") 149 user_data_dir = tempfile.mkdtemp(prefix="chr_")
135 js_flags = "--runtime-call-stats" 150 js_flags = "--runtime-call-stats"
136 if args.replay_wpr: js_flags += " --allow-natives-syntax" 151 if args.replay_wpr: js_flags += " --allow-natives-syntax"
137 if args.js_flags: js_flags += " " + args.js_flags 152 if args.js_flags: js_flags += " " + args.js_flags
138 chrome_flags = [ 153 chrome_flags = [
139 "--no-default-browser-check", 154 "--no-default-browser-check",
140 "--disable-translate", 155 "--disable-translate",
141 "--disable-seccomp-sandbox",
142 "--js-flags={}".format(js_flags), 156 "--js-flags={}".format(js_flags),
143 "--no-first-run", 157 "--no-first-run",
144 "--user-data-dir={}".format(user_data_dir), 158 "--user-data-dir={}".format(user_data_dir),
145 ] 159 ]
146 if args.replay_wpr: 160 if args.replay_wpr:
147 chrome_flags += [ 161 chrome_flags += [
148 "--host-resolver-rules=MAP *:80 localhost:4080, " \ 162 "--host-resolver-rules=MAP *:80 localhost:4080, " \
149 "MAP *:443 localhost:4443, " \ 163 "MAP *:443 localhost:4443, " \
150 "EXCLUDE localhost", 164 "EXCLUDE localhost",
151 "--ignore-certificate-errors", 165 "--ignore-certificate-errors",
166 "--disable-seccomp-sandbox",
152 "--disable-web-security", 167 "--disable-web-security",
153 "--reduce-security-for-testing", 168 "--reduce-security-for-testing",
154 "--allow-insecure-localhost", 169 "--allow-insecure-localhost",
155 ] 170 ]
156 else: 171 else:
157 chrome_flags += [ 172 chrome_flags += [
158 "--single-process", 173 "--single-process",
159 ] 174 ]
160 if args.chrome_flags: 175 if args.chrome_flags:
161 chrome_flags += args.chrome_flags.split() 176 chrome_flags += args.chrome_flags.split()
162 cmd_args = [ 177 cmd_args = [
163 "timeout", str(timeout), 178 "timeout", str(timeout),
164 args.with_chrome 179 args.with_chrome
165 ] + chrome_flags + [ site ] 180 ] + chrome_flags + [ site ]
166 print "- " * 40 181 print "- " * 40
167 print_command(cmd_args) 182 print_command(cmd_args)
168 print "- " * 40 183 print "- " * 40
169 with open(result, "wt") as f: 184 with open(result, "wt") as f:
170 status = subprocess.call(cmd_args, stdout=f) 185 status = subprocess.call(cmd_args, stdout=f)
171 # 124 means timeout killed chrome, 0 means the user was bored first! 186 # 124 means timeout killed chrome, 0 means the user was bored first!
172 # If none of these two happened, then chrome apparently crashed, so 187 # If none of these two happened, then chrome apparently crashed, so
173 # it must be called again. 188 # it must be called again.
174 if status != 124 and status != 0: 189 if status != 124 and status != 0:
175 print("CHROME CRASHED, REPEATING RUN"); 190 print("CHROME CRASHED, REPEATING RUN");
176 continue 191 continue
177 # If the stats file is empty, chrome must be called again. 192 # If the stats file is empty, chrome must be called again.
178 if os.path.isfile(result) and os.path.getsize(result) > 0: 193 if os.path.isfile(result) and os.path.getsize(result) > 0:
179 if args.print_url: 194 if args.print_url:
180 with open(result, "at") as f: 195 with open(result, "at") as f:
181 print >> f 196 print >> f
182 print >> f, "URL: {}".format(site) 197 print >> f, "URL: {}".format(site)
183 break 198 break
184 if retries <= 5: timeout += 1 199 if retries <= 6: timeout += 2 ** (retries-1)
185 print("EMPTY RESULT, REPEATING RUN"); 200 print("EMPTY RESULT, REPEATING RUN");
186 finally: 201 finally:
187 if not args.user_data_dir: 202 if not args.user_data_dir:
188 shutil.rmtree(user_data_dir) 203 shutil.rmtree(user_data_dir)
189 204
190 205
191 def read_sites_file(args): 206 def read_sites_file(args):
192 try: 207 try:
193 sites = [] 208 sites = []
194 try: 209 try:
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 # Process the whole file and sum repeating entries. 301 # Process the whole file and sum repeating entries.
287 D = { 'Sum': {'time': 0, 'count': 0} } 302 D = { 'Sum': {'time': 0, 'count': 0} }
288 for line in f: 303 for line in f:
289 line = line.strip() 304 line = line.strip()
290 # Discard headers and footers. 305 # Discard headers and footers.
291 if not line: continue 306 if not line: continue
292 if line.startswith("Runtime Function"): continue 307 if line.startswith("Runtime Function"): continue
293 if line.startswith("===="): continue 308 if line.startswith("===="): continue
294 if line.startswith("----"): continue 309 if line.startswith("----"): continue
295 if line.startswith("URL:"): continue 310 if line.startswith("URL:"): continue
311 if line.startswith("STATS:"): continue
296 # We have a regular line. 312 # We have a regular line.
297 fields = line.split() 313 fields = line.split()
298 key = fields[0] 314 key = fields[0]
299 time = float(fields[1].replace("ms", "")) 315 time = float(fields[1].replace("ms", ""))
300 count = int(fields[3]) 316 count = int(fields[3])
301 if key not in D: D[key] = { 'time': 0, 'count': 0 } 317 if key not in D: D[key] = { 'time': 0, 'count': 0 }
302 D[key]['time'] += time 318 D[key]['time'] += time
303 D[key]['count'] += count 319 D[key]['count'] += count
304 # We calculate the sum, if it's not the "total" line. 320 # We calculate the sum, if it's not the "total" line.
305 if key != "Total": 321 if key != "Total":
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 409
394 def do_json(args): 410 def do_json(args):
395 J = {} 411 J = {}
396 for path in args.logdirs: 412 for path in args.logdirs:
397 if os.path.isdir(path): 413 if os.path.isdir(path):
398 for root, dirs, files in os.walk(path): 414 for root, dirs, files in os.walk(path):
399 version = os.path.basename(root) 415 version = os.path.basename(root)
400 if version not in J: J[version] = {} 416 if version not in J: J[version] = {}
401 for filename in files: 417 for filename in files:
402 if filename.endswith(".txt"): 418 if filename.endswith(".txt"):
403 m = re.match(r'^([^#]+)(#.*)?$', filename) 419 m = re.match(r'^([^#]+)(#.*)?\.txt$', filename)
404 domain = m.group(1) 420 domain = m.group(1)
405 if domain not in J[version]: J[version][domain] = {} 421 if domain not in J[version]: J[version][domain] = {}
406 read_stats(os.path.join(root, filename), J[version][domain]) 422 read_stats(os.path.join(root, filename), J[version][domain])
407 for version, T in J.items(): 423 for version, T in J.items():
408 for domain, S in T.items(): 424 for domain, S in T.items():
409 A = [] 425 A = []
410 for name, value in S.items(): 426 for name, value in S.items():
411 # We don't want the calculated sum in the JSON file. 427 # We don't want the calculated sum in the JSON file.
412 if name == "Sum": continue 428 if name == "Sum": continue
413 entry = [name] 429 entry = [name]
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 subparsers["run"].add_argument( 471 subparsers["run"].add_argument(
456 "--js-flags", type=str, default="", 472 "--js-flags", type=str, default="",
457 help="specify additional V8 flags") 473 help="specify additional V8 flags")
458 subparsers["run"].add_argument( 474 subparsers["run"].add_argument(
459 "--no-url", dest="print_url", action="store_false", default=True, 475 "--no-url", dest="print_url", action="store_false", default=True,
460 help="do not include url in statistics file") 476 help="do not include url in statistics file")
461 subparsers["run"].add_argument( 477 subparsers["run"].add_argument(
462 "-n", "--repeat", type=int, metavar="<num>", 478 "-n", "--repeat", type=int, metavar="<num>",
463 help="specify iterations for each website (default: once)") 479 help="specify iterations for each website (default: once)")
464 subparsers["run"].add_argument( 480 subparsers["run"].add_argument(
481 "-k", "--refresh", type=int, metavar="<num>", default=0,
482 help="specify refreshes for each iteration (default: 0)")
483 subparsers["run"].add_argument(
465 "--replay-wpr", type=str, metavar="<path>", 484 "--replay-wpr", type=str, metavar="<path>",
466 help="use the specified web page replay (.wpr) archive") 485 help="use the specified web page replay (.wpr) archive")
467 subparsers["run"].add_argument( 486 subparsers["run"].add_argument(
468 "--replay-bin", type=str, metavar="<path>", 487 "--replay-bin", type=str, metavar="<path>",
469 help="specify the replay.py script typically located in " \ 488 help="specify the replay.py script typically located in " \
470 "$CHROMIUM/src/third_party/webpagereplay/replay.py") 489 "$CHROMIUM/src/third_party/webpagereplay/replay.py")
471 subparsers["run"].add_argument( 490 subparsers["run"].add_argument(
472 "-r", "--retries", type=int, metavar="<num>", 491 "-r", "--retries", type=int, metavar="<num>",
473 help="specify retries if website is down (default: forever)") 492 help="specify retries if website is down (default: forever)")
474 subparsers["run"].add_argument( 493 subparsers["run"].add_argument(
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 args.error("use either option --sites-file or site URLs") 547 args.error("use either option --sites-file or site URLs")
529 sys.exit(1) 548 sys.exit(1)
530 elif args.command == "run" and not coexist(args.replay_wpr, args.replay_bin): 549 elif args.command == "run" and not coexist(args.replay_wpr, args.replay_bin):
531 args.error("options --replay-wpr and --replay-bin must be used together") 550 args.error("options --replay-wpr and --replay-bin must be used together")
532 sys.exit(1) 551 sys.exit(1)
533 else: 552 else:
534 args.func(args) 553 args.func(args)
535 554
536 if __name__ == "__main__": 555 if __name__ == "__main__":
537 sys.exit(main()) 556 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