| Index: tools/deep_memory_profiler/dmprof
|
| diff --git a/tools/deep_memory_profiler/dmprof b/tools/deep_memory_profiler/dmprof
|
| index fdf5a7c414ead3853c2f1ba29f649819603bcb06..a2f6919a63ea2afd9a7ef87c40bddf05abe7e619 100755
|
| --- a/tools/deep_memory_profiler/dmprof
|
| +++ b/tools/deep_memory_profiler/dmprof
|
| @@ -66,6 +66,13 @@ appeared_addresses = set()
|
| components = []
|
|
|
|
|
| +class ParsingException(Exception):
|
| + def __init__(self, value):
|
| + self.value = value
|
| + def __str__(self):
|
| + return repr(self.value)
|
| +
|
| +
|
| class Policy(object):
|
|
|
| def __init__(self, name, mmap, pattern):
|
| @@ -112,17 +119,16 @@ class Bucket(object):
|
| class Log(object):
|
|
|
| """A class representing one dumped log data."""
|
| - def __init__(self, log_path, buckets):
|
| + def __init__(self, log_path):
|
| self.log_path = log_path
|
| self.log_lines = [
|
| l for l in open(self.log_path, 'r') if l and not l.startswith('#')]
|
| self.log_version = ''
|
| - sys.stderr.write('parsing a log file:%s\n' % log_path)
|
| + sys.stderr.write('Loading a dump: %s\n' % log_path)
|
| self.mmap_stacktrace_lines = []
|
| self.malloc_stacktrace_lines = []
|
| self.counters = {}
|
| self.log_time = os.stat(self.log_path).st_mtime
|
| - self.parse_log(buckets)
|
|
|
| @staticmethod
|
| def dump_stacktrace_lines(stacktrace_lines, buckets):
|
| @@ -279,13 +285,17 @@ class Log(object):
|
| @staticmethod
|
| def skip_lines_while(line_number, max_line_number, skipping_condition):
|
| """Increments line_number until skipping_condition(line_number) is false.
|
| +
|
| + Returns:
|
| + A pair of an integer indicating a line number after skipped, and a
|
| + boolean value which is True if found a line which skipping_condition
|
| + is False for.
|
| """
|
| while skipping_condition(line_number):
|
| line_number += 1
|
| if line_number >= max_line_number:
|
| - sys.stderr.write('invalid heap profile dump.')
|
| - return line_number
|
| - return line_number
|
| + return line_number, False
|
| + return line_number, True
|
|
|
| def parse_stacktraces_while_valid(self, buckets, log_lines, line_number):
|
| """Parses stacktrace lines while the lines are valid.
|
| @@ -301,11 +311,11 @@ class Log(object):
|
| A pair of a list of valid lines and an integer representing the last
|
| line number in log_lines.
|
| """
|
| - line_number = self.skip_lines_while(
|
| + (line_number, _) = self.skip_lines_while(
|
| line_number, len(log_lines),
|
| lambda n: not log_lines[n].split()[0].isdigit())
|
| stacktrace_lines_start = line_number
|
| - line_number = self.skip_lines_while(
|
| + (line_number, _) = self.skip_lines_while(
|
| line_number, len(log_lines),
|
| lambda n: self.check_stacktrace_line(log_lines[n], buckets))
|
| return (log_lines[stacktrace_lines_start:line_number], line_number)
|
| @@ -323,15 +333,15 @@ class Log(object):
|
| log_lines.
|
|
|
| Raises:
|
| - RuntimeException for invalid dump versions.
|
| + ParsingException for invalid dump versions.
|
| """
|
| - sys.stderr.write(' heap profile dump version: %s\n' % self.log_version)
|
| + sys.stderr.write(' Version: %s\n' % self.log_version)
|
|
|
| if self.log_version in (DUMP_DEEP_3, DUMP_DEEP_4):
|
| (self.mmap_stacktrace_lines, line_number) = (
|
| self.parse_stacktraces_while_valid(
|
| buckets, self.log_lines, line_number))
|
| - line_number = self.skip_lines_while(
|
| + (line_number, _) = self.skip_lines_while(
|
| line_number, len(self.log_lines),
|
| lambda n: self.log_lines[n] != 'MALLOC_STACKTRACES:\n')
|
| (self.malloc_stacktrace_lines, line_number) = (
|
| @@ -342,7 +352,7 @@ class Log(object):
|
| (self.mmap_stacktrace_lines, line_number) = (
|
| self.parse_stacktraces_while_valid(
|
| buckets, self.log_lines, line_number))
|
| - line_number = self.skip_lines_while(
|
| + (line_number, _) = self.skip_lines_while(
|
| line_number, len(self.log_lines),
|
| lambda n: self.log_lines[n] != 'MALLOC_STACKTRACES:\n')
|
| (self.malloc_stacktrace_lines, line_number) = (
|
| @@ -357,12 +367,12 @@ class Log(object):
|
| buckets, self.log_lines, line_number))
|
|
|
| else:
|
| - raise RuntimeError('invalid heap profile dump version: %s' % (
|
| + raise ParsingException('invalid heap profile dump version: %s' % (
|
| self.log_version))
|
|
|
| def parse_global_stats(self):
|
| """Parses lines in self.log_lines as global stats."""
|
| - ln = self.skip_lines_while(
|
| + (ln, _) = self.skip_lines_while(
|
| 0, len(self.log_lines),
|
| lambda n: self.log_lines[n] != 'GLOBAL_STATS:\n')
|
|
|
| @@ -378,7 +388,7 @@ class Log(object):
|
| 'total', 'file', 'anonymous', 'other', 'mmap', 'tcmalloc']
|
|
|
| for prefix in global_stat_names:
|
| - ln = self.skip_lines_while(
|
| + (ln, _) = self.skip_lines_while(
|
| ln, len(self.log_lines),
|
| lambda n: self.log_lines[n].split()[0] != prefix)
|
| words = self.log_lines[ln].split()
|
| @@ -393,26 +403,31 @@ class Log(object):
|
| and an integer indicating a line number next to the version string).
|
|
|
| Raises:
|
| - RuntimeException for invalid dump versions.
|
| + ParsingException for invalid dump versions.
|
| """
|
| version = ''
|
|
|
| # Skip until an identifiable line.
|
| headers = ('STACKTRACES:\n', 'MMAP_STACKTRACES:\n', 'heap profile: ')
|
| - ln = self.skip_lines_while(
|
| + if not self.log_lines:
|
| + raise ParsingException('Empty heap dump file.')
|
| + (ln, found) = self.skip_lines_while(
|
| 0, len(self.log_lines),
|
| lambda n: not self.log_lines[n].startswith(headers))
|
| + if not found:
|
| + raise ParsingException('Invalid heap dump file (no version header).')
|
|
|
| # Identify a version.
|
| if self.log_lines[ln].startswith('heap profile: '):
|
| version = self.log_lines[ln][13:].strip()
|
| if (version == DUMP_DEEP_2 or version == DUMP_DEEP_3 or
|
| version == DUMP_DEEP_4):
|
| - ln = self.skip_lines_while(
|
| + (ln, _) = self.skip_lines_while(
|
| ln, len(self.log_lines),
|
| lambda n: self.log_lines[n] != 'MMAP_STACKTRACES:\n')
|
| else:
|
| - raise RuntimeError('invalid heap profile dump version: %s' % version)
|
| + raise ParsingException('invalid heap profile dump version: %s'
|
| + % version)
|
| elif self.log_lines[ln] == 'STACKTRACES:\n':
|
| version = DUMP_DEEP_1
|
| elif self.log_lines[ln] == 'MMAP_STACKTRACES:\n':
|
| @@ -746,8 +761,6 @@ Examples:
|
| buckets[int(words[0])] = Bucket(words[1:])
|
| n += 1
|
|
|
| - sys.stderr.write('the number buckets: %d\n' % (bucket_count))
|
| -
|
| log_path_list = [log_path]
|
|
|
| if action in ('--csv', '--json'):
|
| @@ -762,7 +775,16 @@ Examples:
|
| break
|
| n += 1
|
|
|
| - logs = [Log(path, buckets) for path in log_path_list]
|
| + logs = []
|
| + for path in log_path_list:
|
| + new_log = Log(path)
|
| + sys.stderr.write('Parsing a dump: %s\n' % path)
|
| + try:
|
| + new_log.parse_log(buckets)
|
| + except ParsingException:
|
| + sys.stderr.write(' Ignored an invalid dump: %s\n' % path)
|
| + else:
|
| + logs.append(new_log)
|
|
|
| sys.stderr.write('getting symbols\n')
|
| update_symbols(symbol_path, maps_lines, chrome_path)
|
|
|