native_heap_classifier.py revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""This module classifies NativeHeap objects filtering their allocations. 6 7The only filter currently available is 'stacktrace', which works as follows: 8 9{'name': 'rule-1', 'stacktrace': 'foo' } 10{'name': 'rule-2', 'stacktrace': ['foo', r'bar\s+baz']} 11 12rule-1 will match any allocation that has 'foo' in one of its stack frames. 13rule-2 will match any allocation that has a stack frame matching 'foo' AND a 14followed by a stack frame matching 'bar baz'. Note that order matters, so rule-2 15will not match a stacktrace like ['bar baz', 'foo']. 16 17TODO(primiano): introduce more filters after the first prototype with UI, for 18instance, filter by source file path, library file name or by allocation size. 19""" 20 21import re 22 23from memory_inspector.classification import results 24from memory_inspector.classification import rules 25from memory_inspector.core import exceptions 26from memory_inspector.core import native_heap 27 28 29_RESULT_KEYS = ['bytes_allocated'] 30 31 32def LoadRules(content): 33 """Loads and parses a native-heap rule tree from a content (string). 34 35 Returns: 36 An instance of |rules.Rule|, which nodes are |_NHeapRule| instances. 37 """ 38 return rules.Load(content, _NHeapRule) 39 40 41def Classify(nativeheap, rule_tree): 42 """Create aggregated results of native heaps using the provided rules. 43 44 Args: 45 nativeheap: the heap dump being processed (a |NativeHeap| instance). 46 rule_tree: the user-defined rules that define the filtering categories. 47 48 Returns: 49 An instance of |AggreatedResults|. 50 """ 51 assert(isinstance(nativeheap, native_heap.NativeHeap)) 52 assert(isinstance(rule_tree, rules.Rule)) 53 54 res = results.AggreatedResults(rule_tree, _RESULT_KEYS) 55 for allocation in nativeheap.allocations: 56 res.AddToMatchingNodes(allocation, [allocation.total_size]) 57 return res 58 59 60class _NHeapRule(rules.Rule): 61 def __init__(self, name, filters): 62 super(_NHeapRule, self).__init__(name) 63 stacktrace_regexs = filters.get('stacktrace', []) 64 # The 'stacktrace' filter can be either a string (simple case, one regex) or 65 # a list of strings (complex case, see doc in the header of this file). 66 if isinstance(stacktrace_regexs, basestring): 67 stacktrace_regexs = [stacktrace_regexs] 68 self._stacktrace_regexs = [] 69 for regex in stacktrace_regexs: 70 try: 71 self._stacktrace_regexs.append(re.compile(regex)) 72 except re.error, descr: 73 raise exceptions.MemoryInspectorException( 74 'Regex parse error "%s" : %s' % (regex, descr)) 75 76 def Match(self, allocation): 77 if not self._stacktrace_regexs: 78 return True 79 cur_regex_idx = 0 80 cur_regex = self._stacktrace_regexs[0] 81 for frame in allocation.stack_trace.frames: 82 if frame.symbol and cur_regex.search(frame.symbol.name): 83 # The current regex has been matched. 84 if cur_regex_idx == len(self._stacktrace_regexs) - 1: 85 return True # All the provided regexs have been matched, we're happy. 86 cur_regex_idx += 1 87 cur_regex = self._stacktrace_regexs[cur_regex_idx] 88 89 return False # Not all the provided regexs have been matched.