17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Copyright 2013 The Chromium Authors. All rights reserved.
27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Use of this source code is governed by a BSD-style license that can be
37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# found in the LICENSE file.
47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport logging
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport os
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochLOGGER = logging.getLogger('dmprof')
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass Dump(object):
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  """Represents a heap profile dump."""
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  def __init__(self):
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    pass
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def path(self):
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def count(self):
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def time(self):
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def iter_map(self):
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def iter_stacktrace(self):
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def global_stat(self, name):
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def run_id(self):
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def pagesize(self):
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def pageframe_length(self):
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def pageframe_encoding(self):
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @property
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def has_pagecount(self):
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    raise NotImplementedError
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @staticmethod
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def load(path, log_header='Loading a heap profile dump: '):
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    """Loads a heap profile dump.
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Args:
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        path: A file path string to load.
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        log_header: A preceding string for log messages.
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Returns:
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        A loaded Dump object.
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Raises:
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ParsingException for invalid heap profile dumps.
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    """
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    from lib.deep_dump import DeepDump
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    dump = DeepDump(path, os.stat(path).st_mtime)
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    with open(path, 'r') as f:
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      dump.load_file(f, log_header)
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return dump
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass DumpList(object):
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  """Represents a sequence of heap profile dumps.
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Individual dumps are loaded into memory lazily as the sequence is accessed,
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  either while being iterated through or randomly accessed.  Loaded dumps are
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  not cached, meaning a newly loaded Dump object is returned every time an
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  element in the list is accessed.
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  """
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  def __init__(self, dump_path_list):
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    self._dump_path_list = dump_path_list
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @staticmethod
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def load(path_list):
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return DumpList(path_list)
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __len__(self):
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return len(self._dump_path_list)
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __iter__(self):
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for dump in self._dump_path_list:
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      yield Dump.load(dump)
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __getitem__(self, index):
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return Dump.load(self._dump_path_list[index])
106