diff options
author | wensheng.he <wensheng.he@samsung.com> | 2014-11-04 18:14:21 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-05 02:14:34 +0000 |
commit | 09714684ace60105a81c539516b945fe4d0b3d65 (patch) | |
tree | dab9a258049d80697401961796e322325a98ddf3 | |
parent | a38b75a3f63048c0c18c6808f3f48f311f309991 (diff) | |
download | chromium_src-09714684ace60105a81c539516b945fe4d0b3d65.zip chromium_src-09714684ace60105a81c539516b945fe4d0b3d65.tar.gz chromium_src-09714684ace60105a81c539516b945fe4d0b3d65.tar.bz2 |
Add a new command to summarize memory usage by function addresses in dmprof
The output format is:
vss1;rss1;addr1;symbol1
vss2;rss2;addr2;symbol2
...
The symbol is related to the addr. If the binary file has symbols, it just same as before:function@sourcefile.
Otherwise it will show the pathname the addr belongs to (mainly it's the library).
This new command could be helpful for lcation leaks.
R=kouhei@chromium.org
BUG=427393
Review URL: https://codereview.chromium.org/700773002
Cr-Commit-Position: refs/heads/master@{#302745}
-rw-r--r-- | tools/deep_memory_profiler/dmprof.py | 1 | ||||
-rw-r--r-- | tools/deep_memory_profiler/subcommands/__init__.py | 1 | ||||
-rw-r--r-- | tools/deep_memory_profiler/subcommands/addr.py | 88 |
3 files changed, 90 insertions, 0 deletions
diff --git a/tools/deep_memory_profiler/dmprof.py b/tools/deep_memory_profiler/dmprof.py index 0cb030a..85c1f6d 100644 --- a/tools/deep_memory_profiler/dmprof.py +++ b/tools/deep_memory_profiler/dmprof.py @@ -19,6 +19,7 @@ LOGGER = logging.getLogger('dmprof') def main(): COMMANDS = { + 'addr': subcommands.AddrCommand, 'buckets': subcommands.BucketsCommand, 'cat': subcommands.CatCommand, 'csv': subcommands.CSVCommand, diff --git a/tools/deep_memory_profiler/subcommands/__init__.py b/tools/deep_memory_profiler/subcommands/__init__.py index 4fb29d0..cc28dfd 100644 --- a/tools/deep_memory_profiler/subcommands/__init__.py +++ b/tools/deep_memory_profiler/subcommands/__init__.py @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +from subcommands.addr import AddrCommand from subcommands.buckets import BucketsCommand from subcommands.cat import CatCommand from subcommands.expand import ExpandCommand diff --git a/tools/deep_memory_profiler/subcommands/addr.py b/tools/deep_memory_profiler/subcommands/addr.py new file mode 100644 index 0000000..ee399e8 --- /dev/null +++ b/tools/deep_memory_profiler/subcommands/addr.py @@ -0,0 +1,88 @@ +# 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 sys +import re + +from lib.subcommand import SubCommand + + +LOGGER = logging.getLogger('dmprof') + + +class AddrCommand(SubCommand): + def __init__(self): + super(AddrCommand, self).__init__('Usage: %prog addr <dump-file>') + + def do(self, sys_argv, out=sys.stdout): + _, args = self._parse_args(sys_argv, 1) + dump_path = args[1] + (bucket_set, dump) = SubCommand.load_basic_files(dump_path, False) + AddrCommand._output(dump, bucket_set, out) + return 0 + + @staticmethod + def _output(dump, bucket_set, out): + """Prints memory usage by function addresses with resolving symbols. + + Args: + bucket_set: A BucketSet object. + out: An IO object to output. + """ + sizes = {} + library = {} + + _ADDR_PATTERN = re.compile(r'^0x[a-f0-9]+$', re.IGNORECASE) + _TCMALLOC_PATTERN = re.compile(r'.*(ProfilerMalloc|MemoryRegionMap::' + '|TypeProfilerMalloc|DoAllocWithArena|SbrkSysAllocator::Alloc' + '|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc' + '|LowLevelAlloc::AllocWithArena).*', re.IGNORECASE) + + for bucket_id, virtual, committed, _, _ in dump.iter_stacktrace: + bucket = bucket_set.get(bucket_id) + if not bucket: + AddrCommand._add_size(bucket_id, "bucket", virtual, committed, sizes) + continue + + if _TCMALLOC_PATTERN.match(bucket.symbolized_joined_stackfunction): + AddrCommand._add_size("TCMALLOC", "TCMALLOC", + virtual, committed, sizes) + continue + + for index, addr in enumerate(bucket.stacktrace): + if _ADDR_PATTERN.match(bucket.symbolized_stackfunction[index]): + AddrCommand._find_library(addr, dump, library) + AddrCommand._add_size(hex(addr), library[addr], + virtual, committed, sizes) + else: + AddrCommand._add_size(hex(addr), + bucket.symbolized_stackfunction[index] + + "@" + bucket.symbolized_stacksourcefile[index], + virtual, committed, sizes) + + for key in sorted(sizes): + out.write('%s;%s;%s;%s\n' % (sizes[key]["vss"], sizes[key]["rss"], + key, sizes[key]["desc"])) + + + @staticmethod + def _add_size(key, desc, vss, rss, sizes): + if not key in sizes: + sizes[key] = {"desc":desc, "vss":0, "rss":0, "alloc":0, "free": 0} + if sizes[key]["desc"] == desc: + sizes[key]["vss"] += vss + sizes[key]["rss"] += rss + else: + sys.stderr.write('%s:(%s) or (%s)?\n' % (key, sizes[key]["desc"], desc)) + sys.exit(1) + + @staticmethod + def _find_library(func, dump, library): + if not func in library: + library[func] = "Unknown" + for addr, region in dump.iter_map: + if addr[0] >= func and func < addr[1]: + library[func] = region[1]['vma']['name'] + break
\ No newline at end of file |