Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: tools/deep_memory_profiler/lib/pageframe.py

Issue 19346002: Refactor dmprof: Split dmprof.py into modules. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/deep_memory_profiler/lib/ordered_dict.py ('k') | tools/deep_memory_profiler/lib/policy.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/deep_memory_profiler/lib/pageframe.py
diff --git a/tools/deep_memory_profiler/lib/pageframe.py b/tools/deep_memory_profiler/lib/pageframe.py
new file mode 100644
index 0000000000000000000000000000000000000000..8722243baf611cde0703f550d5b48c9f38138ab9
--- /dev/null
+++ b/tools/deep_memory_profiler/lib/pageframe.py
@@ -0,0 +1,163 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import re
+import struct
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+class PageFrame(object):
+ """Represents a pageframe and maybe its shared count."""
+ def __init__(self, pfn, size, pagecount, start_truncated, end_truncated):
+ self._pfn = pfn
+ self._size = size
+ self._pagecount = pagecount
+ self._start_truncated = start_truncated
+ self._end_truncated = end_truncated
+
+ def __str__(self):
+ result = str()
+ if self._start_truncated:
+ result += '<'
+ result += '%06x#%d' % (self._pfn, self._pagecount)
+ if self._end_truncated:
+ result += '>'
+ return result
+
+ def __repr__(self):
+ return str(self)
+
+ @staticmethod
+ def parse(encoded_pfn, size):
+ start = 0
+ end = len(encoded_pfn)
+ end_truncated = False
+ if encoded_pfn.endswith('>'):
+ end = len(encoded_pfn) - 1
+ end_truncated = True
+ pagecount_found = encoded_pfn.find('#')
+ pagecount = None
+ if pagecount_found >= 0:
+ encoded_pagecount = 'AAA' + encoded_pfn[pagecount_found+1 : end]
+ pagecount = struct.unpack(
+ '>I', '\x00' + encoded_pagecount.decode('base64'))[0]
+ end = pagecount_found
+ start_truncated = False
+ if encoded_pfn.startswith('<'):
+ start = 1
+ start_truncated = True
+
+ pfn = struct.unpack(
+ '>I', '\x00' + (encoded_pfn[start:end]).decode('base64'))[0]
+
+ return PageFrame(pfn, size, pagecount, start_truncated, end_truncated)
+
+ @property
+ def pfn(self):
+ return self._pfn
+
+ @property
+ def size(self):
+ return self._size
+
+ def set_size(self, size):
+ self._size = size
+
+ @property
+ def pagecount(self):
+ return self._pagecount
+
+ @property
+ def start_truncated(self):
+ return self._start_truncated
+
+ @property
+ def end_truncated(self):
+ return self._end_truncated
+
+
+class PFNCounts(object):
+ """Represents counts of PFNs in a process."""
+
+ _PATH_PATTERN = re.compile(r'^(.*)\.([0-9]+)\.([0-9]+)\.heap$')
+
+ def __init__(self, path, modified_time):
+ matched = self._PATH_PATTERN.match(path)
+ if matched:
+ self._pid = int(matched.group(2))
+ else:
+ self._pid = 0
+ self._command_line = ''
+ self._pagesize = 4096
+ self._path = path
+ self._pfn_meta = ''
+ self._pfnset = {}
+ self._reason = ''
+ self._time = modified_time
+
+ @staticmethod
+ def load(path, log_header='Loading PFNs from a heap profile dump: '):
+ pfnset = PFNCounts(path, float(os.stat(path).st_mtime))
+ LOGGER.info('%s%s' % (log_header, path))
+
+ with open(path, 'r') as pfnset_f:
+ pfnset.load_file(pfnset_f)
+
+ return pfnset
+
+ @property
+ def path(self):
+ return self._path
+
+ @property
+ def pid(self):
+ return self._pid
+
+ @property
+ def time(self):
+ return self._time
+
+ @property
+ def reason(self):
+ return self._reason
+
+ @property
+ def iter_pfn(self):
+ for pfn, count in self._pfnset.iteritems():
+ yield pfn, count
+
+ def load_file(self, pfnset_f):
+ prev_pfn_end_truncated = None
+ for line in pfnset_f:
+ line = line.strip()
+ if line.startswith('GLOBAL_STATS:') or line.startswith('STACKTRACES:'):
+ break
+ elif line.startswith('PF: '):
+ for encoded_pfn in line[3:].split():
+ page_frame = PageFrame.parse(encoded_pfn, self._pagesize)
+ if page_frame.start_truncated and (
+ not prev_pfn_end_truncated or
+ prev_pfn_end_truncated != page_frame.pfn):
+ LOGGER.error('Broken page frame number: %s.' % encoded_pfn)
+ self._pfnset[page_frame.pfn] = self._pfnset.get(page_frame.pfn, 0) + 1
+ if page_frame.end_truncated:
+ prev_pfn_end_truncated = page_frame.pfn
+ else:
+ prev_pfn_end_truncated = None
+ elif line.startswith('PageSize: '):
+ self._pagesize = int(line[10:])
+ elif line.startswith('PFN: '):
+ self._pfn_meta = line[5:]
+ elif line.startswith('PageFrame: '):
+ self._pfn_meta = line[11:]
+ elif line.startswith('Time: '):
+ self._time = float(line[6:])
+ elif line.startswith('CommandLine: '):
+ self._command_line = line[13:]
+ elif line.startswith('Reason: '):
+ self._reason = line[8:]
« no previous file with comments | « tools/deep_memory_profiler/lib/ordered_dict.py ('k') | tools/deep_memory_profiler/lib/policy.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698