OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2008 the V8 project authors. All rights reserved. | 3 # Copyright 2008 the V8 project authors. All rights reserved. |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 16 matching lines...) Expand all Loading... |
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | 29 |
30 | 30 |
31 """A cross-platform execution counter viewer. | 31 """A cross-platform execution counter viewer. |
32 | 32 |
33 The stats viewer reads counters from a binary file and displays them | 33 The stats viewer reads counters from a binary file and displays them |
34 in a window, re-reading and re-displaying with regular intervals. | 34 in a window, re-reading and re-displaying with regular intervals. |
35 """ | 35 """ |
36 | 36 |
37 | |
38 import mmap | 37 import mmap |
| 38 import optparse |
39 import os | 39 import os |
40 import re | 40 import re |
41 import struct | 41 import struct |
42 import sys | 42 import sys |
43 import time | 43 import time |
44 import Tkinter | 44 import Tkinter |
45 | 45 |
46 | 46 |
47 # The interval, in milliseconds, between ui updates | 47 # The interval, in milliseconds, between ui updates |
48 UPDATE_INTERVAL_MS = 100 | 48 UPDATE_INTERVAL_MS = 100 |
49 | 49 |
50 | 50 |
51 # Mapping from counter prefix to the formatting to be used for the counter | 51 # Mapping from counter prefix to the formatting to be used for the counter |
52 COUNTER_LABELS = {"t": "%i ms.", "c": "%i"} | 52 COUNTER_LABELS = {"t": "%i ms.", "c": "%i"} |
53 | 53 |
54 | 54 |
55 # The magic numbers used to check if a file is not a counters file | 55 # The magic numbers used to check if a file is not a counters file |
56 COUNTERS_FILE_MAGIC_NUMBER = 0xDEADFACE | 56 COUNTERS_FILE_MAGIC_NUMBER = 0xDEADFACE |
57 CHROME_COUNTERS_FILE_MAGIC_NUMBER = 0x13131313 | 57 CHROME_COUNTERS_FILE_MAGIC_NUMBER = 0x13131313 |
58 | 58 |
59 | 59 |
60 class StatsViewer(object): | 60 class StatsViewer(object): |
61 """The main class that keeps the data used by the stats viewer.""" | 61 """The main class that keeps the data used by the stats viewer.""" |
62 | 62 |
63 def __init__(self, data_name): | 63 def __init__(self, data_name, name_filter): |
64 """Creates a new instance. | 64 """Creates a new instance. |
65 | 65 |
66 Args: | 66 Args: |
67 data_name: the name of the file containing the counters. | 67 data_name: the name of the file containing the counters. |
| 68 name_filter: The regexp filter to apply to counter names. |
68 """ | 69 """ |
69 self.data_name = data_name | 70 self.data_name = data_name |
| 71 self.name_filter = name_filter |
70 | 72 |
71 # The handle created by mmap.mmap to the counters file. We need | 73 # The handle created by mmap.mmap to the counters file. We need |
72 # this to clean it up on exit. | 74 # this to clean it up on exit. |
73 self.shared_mmap = None | 75 self.shared_mmap = None |
74 | 76 |
75 # A mapping from counter names to the ui element that displays | 77 # A mapping from counter names to the ui element that displays |
76 # them | 78 # them |
77 self.ui_counters = {} | 79 self.ui_counters = {} |
78 | 80 |
79 # The counter collection used to access the counters file | 81 # The counter collection used to access the counters file |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 self.ui_counters.clear() | 219 self.ui_counters.clear() |
218 for child in self.root.children.values(): | 220 for child in self.root.children.values(): |
219 child.destroy() | 221 child.destroy() |
220 | 222 |
221 # Build new ui | 223 # Build new ui |
222 index = 0 | 224 index = 0 |
223 sorted_groups = groups.keys() | 225 sorted_groups = groups.keys() |
224 sorted_groups.sort() | 226 sorted_groups.sort() |
225 for counter_name in sorted_groups: | 227 for counter_name in sorted_groups: |
226 counter_objs = groups[counter_name] | 228 counter_objs = groups[counter_name] |
227 name = Tkinter.Label(self.root, width=50, anchor=Tkinter.W, | 229 if self.name_filter.match(counter_name): |
228 text=counter_name) | 230 name = Tkinter.Label(self.root, width=50, anchor=Tkinter.W, |
229 name.grid(row=index, column=0, padx=1, pady=1) | 231 text=counter_name) |
| 232 name.grid(row=index, column=0, padx=1, pady=1) |
230 count = len(counter_objs) | 233 count = len(counter_objs) |
231 for i in xrange(count): | 234 for i in xrange(count): |
232 counter = counter_objs[i] | 235 counter = counter_objs[i] |
233 name = counter.Name() | 236 name = counter.Name() |
234 var = Tkinter.StringVar() | 237 var = Tkinter.StringVar() |
235 value = Tkinter.Label(self.root, width=15, anchor=Tkinter.W, | 238 if self.name_filter.match(name): |
236 textvariable=var) | 239 value = Tkinter.Label(self.root, width=15, anchor=Tkinter.W, |
237 value.grid(row=index, column=(1 + i), padx=1, pady=1) | 240 textvariable=var) |
| 241 value.grid(row=index, column=(1 + i), padx=1, pady=1) |
238 | 242 |
239 # If we know how to interpret the prefix of this counter then | 243 # If we know how to interpret the prefix of this counter then |
240 # add an appropriate formatting to the variable | 244 # add an appropriate formatting to the variable |
241 if (":" in name) and (name[0] in COUNTER_LABELS): | 245 if (":" in name) and (name[0] in COUNTER_LABELS): |
242 format = COUNTER_LABELS[name[0]] | 246 format = COUNTER_LABELS[name[0]] |
243 else: | 247 else: |
244 format = "%i" | 248 format = "%i" |
245 ui_counter = UiCounter(var, format) | 249 ui_counter = UiCounter(var, format) |
246 self.ui_counters[name] = ui_counter | 250 self.ui_counters[name] = ui_counter |
247 ui_counter.Set(counter.Value()) | 251 ui_counter.Set(counter.Value()) |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 return i | 437 return i |
434 return self.max_counters | 438 return self.max_counters |
435 | 439 |
436 def Counter(self, i): | 440 def Counter(self, i): |
437 """Return the i'th counter.""" | 441 """Return the i'th counter.""" |
438 return ChromeCounter(self.data, | 442 return ChromeCounter(self.data, |
439 self.counter_names_offset + i * self._NAME_SIZE, | 443 self.counter_names_offset + i * self._NAME_SIZE, |
440 self.counter_values_offset + i * self.max_threads * 4) | 444 self.counter_values_offset + i * self.max_threads * 4) |
441 | 445 |
442 | 446 |
443 def Main(data_file): | 447 def Main(data_file, name_filter): |
444 """Run the stats counter. | 448 """Run the stats counter. |
445 | 449 |
446 Args: | 450 Args: |
447 data_file: The counters file to monitor. | 451 data_file: The counters file to monitor. |
| 452 name_filter: The regexp filter to apply to counter names. |
448 """ | 453 """ |
449 StatsViewer(data_file).Run() | 454 StatsViewer(data_file, name_filter).Run() |
450 | 455 |
451 | 456 |
452 if __name__ == "__main__": | 457 if __name__ == "__main__": |
453 if len(sys.argv) != 2: | 458 parser = optparse.OptionParser("usage: %prog [--filter=re] " |
454 print "Usage: stats-viewer.py <stats data>|<test_shell pid>" | 459 "<stats data>|<test_shell pid>") |
| 460 parser.add_option("--filter", |
| 461 default=".*", |
| 462 help=("regexp filter for counter names " |
| 463 "[default: %default]")) |
| 464 (options, args) = parser.parse_args() |
| 465 if len(args) != 1: |
| 466 parser.print_help() |
455 sys.exit(1) | 467 sys.exit(1) |
456 Main(sys.argv[1]) | 468 Main(args[0], re.compile(options.filter)) |
OLD | NEW |