Revert of Remove OneClickSigninHelper since it is no longer used. (patchset #5 id...
[chromium-blink-merge.git] / tools / deep_memory_profiler / lib / pageframe.py
blob8722243baf611cde0703f550d5b48c9f38138ab9
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
3 # found in the LICENSE file.
5 import logging
6 import os
7 import re
8 import struct
11 LOGGER = logging.getLogger('dmprof')
14 class PageFrame(object):
15 """Represents a pageframe and maybe its shared count."""
16 def __init__(self, pfn, size, pagecount, start_truncated, end_truncated):
17 self._pfn = pfn
18 self._size = size
19 self._pagecount = pagecount
20 self._start_truncated = start_truncated
21 self._end_truncated = end_truncated
23 def __str__(self):
24 result = str()
25 if self._start_truncated:
26 result += '<'
27 result += '%06x#%d' % (self._pfn, self._pagecount)
28 if self._end_truncated:
29 result += '>'
30 return result
32 def __repr__(self):
33 return str(self)
35 @staticmethod
36 def parse(encoded_pfn, size):
37 start = 0
38 end = len(encoded_pfn)
39 end_truncated = False
40 if encoded_pfn.endswith('>'):
41 end = len(encoded_pfn) - 1
42 end_truncated = True
43 pagecount_found = encoded_pfn.find('#')
44 pagecount = None
45 if pagecount_found >= 0:
46 encoded_pagecount = 'AAA' + encoded_pfn[pagecount_found+1 : end]
47 pagecount = struct.unpack(
48 '>I', '\x00' + encoded_pagecount.decode('base64'))[0]
49 end = pagecount_found
50 start_truncated = False
51 if encoded_pfn.startswith('<'):
52 start = 1
53 start_truncated = True
55 pfn = struct.unpack(
56 '>I', '\x00' + (encoded_pfn[start:end]).decode('base64'))[0]
58 return PageFrame(pfn, size, pagecount, start_truncated, end_truncated)
60 @property
61 def pfn(self):
62 return self._pfn
64 @property
65 def size(self):
66 return self._size
68 def set_size(self, size):
69 self._size = size
71 @property
72 def pagecount(self):
73 return self._pagecount
75 @property
76 def start_truncated(self):
77 return self._start_truncated
79 @property
80 def end_truncated(self):
81 return self._end_truncated
84 class PFNCounts(object):
85 """Represents counts of PFNs in a process."""
87 _PATH_PATTERN = re.compile(r'^(.*)\.([0-9]+)\.([0-9]+)\.heap$')
89 def __init__(self, path, modified_time):
90 matched = self._PATH_PATTERN.match(path)
91 if matched:
92 self._pid = int(matched.group(2))
93 else:
94 self._pid = 0
95 self._command_line = ''
96 self._pagesize = 4096
97 self._path = path
98 self._pfn_meta = ''
99 self._pfnset = {}
100 self._reason = ''
101 self._time = modified_time
103 @staticmethod
104 def load(path, log_header='Loading PFNs from a heap profile dump: '):
105 pfnset = PFNCounts(path, float(os.stat(path).st_mtime))
106 LOGGER.info('%s%s' % (log_header, path))
108 with open(path, 'r') as pfnset_f:
109 pfnset.load_file(pfnset_f)
111 return pfnset
113 @property
114 def path(self):
115 return self._path
117 @property
118 def pid(self):
119 return self._pid
121 @property
122 def time(self):
123 return self._time
125 @property
126 def reason(self):
127 return self._reason
129 @property
130 def iter_pfn(self):
131 for pfn, count in self._pfnset.iteritems():
132 yield pfn, count
134 def load_file(self, pfnset_f):
135 prev_pfn_end_truncated = None
136 for line in pfnset_f:
137 line = line.strip()
138 if line.startswith('GLOBAL_STATS:') or line.startswith('STACKTRACES:'):
139 break
140 elif line.startswith('PF: '):
141 for encoded_pfn in line[3:].split():
142 page_frame = PageFrame.parse(encoded_pfn, self._pagesize)
143 if page_frame.start_truncated and (
144 not prev_pfn_end_truncated or
145 prev_pfn_end_truncated != page_frame.pfn):
146 LOGGER.error('Broken page frame number: %s.' % encoded_pfn)
147 self._pfnset[page_frame.pfn] = self._pfnset.get(page_frame.pfn, 0) + 1
148 if page_frame.end_truncated:
149 prev_pfn_end_truncated = page_frame.pfn
150 else:
151 prev_pfn_end_truncated = None
152 elif line.startswith('PageSize: '):
153 self._pagesize = int(line[10:])
154 elif line.startswith('PFN: '):
155 self._pfn_meta = line[5:]
156 elif line.startswith('PageFrame: '):
157 self._pfn_meta = line[11:]
158 elif line.startswith('Time: '):
159 self._time = float(line[6:])
160 elif line.startswith('CommandLine: '):
161 self._command_line = line[13:]
162 elif line.startswith('Reason: '):
163 self._reason = line[8:]