OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import cStringIO | 5 import cStringIO |
6 import json | 6 import json |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import re | 9 import re |
10 | 10 |
11 | 11 |
12 LOGGER = logging.getLogger('dmprof') | 12 LOGGER = logging.getLogger('dmprof') |
13 | 13 |
14 BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | 14 BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
15 | 15 |
16 DEFAULT_SORTERS = [ | 16 DEFAULT_SORTERS = [ |
17 os.path.join(BASE_PATH, 'sorter.malloc-component.json'), | 17 os.path.join(BASE_PATH, 'sorter.malloc-component.json'), |
18 os.path.join(BASE_PATH, 'sorter.malloc-type.json'), | 18 os.path.join(BASE_PATH, 'sorter.malloc-type.json'), |
19 os.path.join(BASE_PATH, 'sorter.vm-map.json'), | 19 os.path.join(BASE_PATH, 'sorter.vm-map.json'), |
20 os.path.join(BASE_PATH, 'sorter.vm-sharing.json'), | 20 os.path.join(BASE_PATH, 'sorter.vm-sharing.json'), |
21 ] | 21 ] |
22 | 22 |
| 23 DEFAULT_TEMPLATES = os.path.join(BASE_PATH, 'templates.json') |
| 24 |
23 | 25 |
24 class Unit(object): | 26 class Unit(object): |
25 """Represents a minimum unit of memory usage categorization. | 27 """Represents a minimum unit of memory usage categorization. |
26 | 28 |
27 It is supposed to be inherited for some different spaces like the entire | 29 It is supposed to be inherited for some different spaces like the entire |
28 virtual memory and malloc arena. Such different spaces are called "worlds" | 30 virtual memory and malloc arena. Such different spaces are called "worlds" |
29 in dmprof. (For example, the "vm" world and the "malloc" world.) | 31 in dmprof. (For example, the "vm" world and the "malloc" world.) |
30 """ | 32 """ |
31 def __init__(self, unit_id, size): | 33 def __init__(self, unit_id, size): |
32 self._unit_id = unit_id | 34 self._unit_id = unit_id |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 if not overwrite and unit.unit_id in self._units: | 147 if not overwrite and unit.unit_id in self._units: |
146 LOGGER.error('The unit id=%s already exists.' % str(unit.unit_id)) | 148 LOGGER.error('The unit id=%s already exists.' % str(unit.unit_id)) |
147 self._units[unit.unit_id] = unit | 149 self._units[unit.unit_id] = unit |
148 | 150 |
149 | 151 |
150 class AbstractRule(object): | 152 class AbstractRule(object): |
151 """An abstract class for rules to be matched with units.""" | 153 """An abstract class for rules to be matched with units.""" |
152 def __init__(self, dct): | 154 def __init__(self, dct): |
153 self._name = dct['name'] | 155 self._name = dct['name'] |
154 self._hidden = dct.get('hidden', False) | 156 self._hidden = dct.get('hidden', False) |
155 self._subworlds = dct.get('subworlds', []) | 157 self._subs = dct.get('subs', []) |
156 | 158 |
157 def match(self, unit): | 159 def match(self, unit): |
158 raise NotImplementedError() | 160 raise NotImplementedError() |
159 | 161 |
160 @property | 162 @property |
161 def name(self): | 163 def name(self): |
162 return self._name | 164 return self._name |
163 | 165 |
164 @property | 166 @property |
165 def hidden(self): | 167 def hidden(self): |
166 return self._hidden | 168 return self._hidden |
167 | 169 |
168 def iter_subworld(self): | 170 def iter_subs(self): |
169 for subworld in self._subworlds: | 171 for sub in self._subs: |
170 yield subworld | 172 yield sub |
171 | 173 |
172 | 174 |
173 class VMRule(AbstractRule): | 175 class VMRule(AbstractRule): |
174 """Represents a Rule to match with virtual memory regions.""" | 176 """Represents a Rule to match with virtual memory regions.""" |
175 def __init__(self, dct): | 177 def __init__(self, dct): |
176 super(VMRule, self).__init__(dct) | 178 super(VMRule, self).__init__(dct) |
177 self._backtrace_function = dct.get('backtrace_function', None) | 179 self._backtrace_function = dct.get('backtrace_function', None) |
178 if self._backtrace_function: | 180 if self._backtrace_function: |
179 self._backtrace_function = re.compile(self._backtrace_function) | 181 self._backtrace_function = re.compile(self._backtrace_function) |
180 self._backtrace_sourcefile = dct.get('backtrace_sourcefile', None) | 182 self._backtrace_sourcefile = dct.get('backtrace_sourcefile', None) |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 return self._no_bucket | 323 return self._no_bucket |
322 | 324 |
323 | 325 |
324 class AbstractSorter(object): | 326 class AbstractSorter(object): |
325 """An abstract class for classifying Units with a set of Rules.""" | 327 """An abstract class for classifying Units with a set of Rules.""" |
326 def __init__(self, dct): | 328 def __init__(self, dct): |
327 self._type = 'sorter' | 329 self._type = 'sorter' |
328 self._version = dct['version'] | 330 self._version = dct['version'] |
329 self._world = dct['world'] | 331 self._world = dct['world'] |
330 self._name = dct['name'] | 332 self._name = dct['name'] |
| 333 self._root = dct.get('root', False) |
331 self._order = dct['order'] | 334 self._order = dct['order'] |
332 | 335 |
333 self._rules = [] | 336 self._rules = [] |
334 for rule in dct['rules']: | 337 for rule in dct['rules']: |
335 if dct['world'] == 'vm': | 338 if dct['world'] == 'vm': |
336 self._rules.append(VMRule(rule)) | 339 self._rules.append(VMRule(rule)) |
337 elif dct['world'] == 'malloc': | 340 elif dct['world'] == 'malloc': |
338 self._rules.append(MallocRule(rule)) | 341 self._rules.append(MallocRule(rule)) |
339 else: | 342 else: |
340 LOGGER.error('Unknown sorter world type') | 343 LOGGER.error('Unknown sorter world type') |
(...skipping 20 matching lines...) Expand all Loading... |
361 return None | 364 return None |
362 | 365 |
363 @property | 366 @property |
364 def world(self): | 367 def world(self): |
365 return self._world | 368 return self._world |
366 | 369 |
367 @property | 370 @property |
368 def name(self): | 371 def name(self): |
369 return self._name | 372 return self._name |
370 | 373 |
| 374 @property |
| 375 def root(self): |
| 376 return self._root |
| 377 |
371 def find(self, unit): | 378 def find(self, unit): |
372 raise NotImplementedError() | 379 raise NotImplementedError() |
373 | 380 |
374 def find_rule(self, name): | 381 def find_rule(self, name): |
375 """Finds a rule whose name is |name|. """ | 382 """Finds a rule whose name is |name|. """ |
376 for rule in self._rules: | 383 for rule in self._rules: |
377 if rule.name == name: | 384 if rule.name == name: |
378 return rule | 385 return rule |
379 return None | 386 return None |
380 | 387 |
(...skipping 26 matching lines...) Expand all Loading... |
407 if unit.bucket.component_cache: | 414 if unit.bucket.component_cache: |
408 return unit.bucket.component_cache | 415 return unit.bucket.component_cache |
409 | 416 |
410 for rule in self._rules: | 417 for rule in self._rules: |
411 if rule.match(unit): | 418 if rule.match(unit): |
412 unit.bucket.component_cache = rule | 419 unit.bucket.component_cache = rule |
413 return rule | 420 return rule |
414 assert False | 421 assert False |
415 | 422 |
416 | 423 |
| 424 class SorterTemplates(object): |
| 425 """Represents a template for sorters.""" |
| 426 def __init__(self, dct): |
| 427 self._dict = dct |
| 428 |
| 429 def as_dict(self): |
| 430 return self._dict |
| 431 |
| 432 @staticmethod |
| 433 def load(filename): |
| 434 with open(filename) as templates_f: |
| 435 templates_dict = json.load(templates_f) |
| 436 return SorterTemplates(templates_dict) |
| 437 |
| 438 |
417 class SorterSet(object): | 439 class SorterSet(object): |
418 """Represents an iterable set of Sorters.""" | 440 """Represents an iterable set of Sorters.""" |
419 def __init__(self, additional=None, default=None): | 441 def __init__(self, additional=None, default=None): |
420 if not additional: | 442 if not additional: |
421 additional = [] | 443 additional = [] |
422 if not default: | 444 if not default: |
423 default = DEFAULT_SORTERS | 445 default = DEFAULT_SORTERS |
424 self._sorters = {} | 446 self._sorters = {} |
425 for filename in default + additional: | 447 for filename in default + additional: |
426 sorter = AbstractSorter.load(filename) | 448 sorter = AbstractSorter.load(filename) |
427 if sorter.world not in self._sorters: | 449 if sorter.world not in self._sorters: |
428 self._sorters[sorter.world] = [] | 450 self._sorters[sorter.world] = [] |
429 self._sorters[sorter.world].append(sorter) | 451 self._sorters[sorter.world].append(sorter) |
| 452 self._templates = SorterTemplates.load(DEFAULT_TEMPLATES) |
430 | 453 |
431 def __repr__(self): | 454 def __repr__(self): |
432 result = cStringIO.StringIO() | 455 result = cStringIO.StringIO() |
433 result.write(self._sorters) | 456 result.write(self._sorters) |
434 return result.getvalue() | 457 return result.getvalue() |
435 | 458 |
436 def __iter__(self): | 459 def __iter__(self): |
437 for sorters in self._sorters.itervalues(): | 460 for sorters in self._sorters.itervalues(): |
438 for sorter in sorters: | 461 for sorter in sorters: |
439 yield sorter | 462 yield sorter |
440 | 463 |
441 def iter_world(self, world): | 464 def iter_world(self, world): |
442 for sorter in self._sorters.get(world, []): | 465 for sorter in self._sorters.get(world, []): |
443 yield sorter | 466 yield sorter |
| 467 |
| 468 @property |
| 469 def templates(self): |
| 470 return self._templates |
OLD | NEW |