| 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 |