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

Side by Side Diff: tools/deep_memory_profiler/dmprof

Issue 10795043: Use find_runtime_symbols in dmprof. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: recovered download.sh. Created 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/deep_memory_profiler/download.sh » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """The deep heap profiler script for Chrome.""" 6 """The deep heap profiler script for Chrome."""
7 7
8 from datetime import datetime 8 from datetime import datetime
9 import json 9 import json
10 import os 10 import os
11 import re 11 import re
12 import shutil
12 import subprocess 13 import subprocess
13 import sys 14 import sys
14 import tempfile 15 import tempfile
15 16
17 FIND_RUNTIME_SYMBOLS_PATH = os.path.join(
18 os.path.dirname(os.path.abspath(__file__)),
19 os.pardir,
20 'find_runtime_symbols')
21 sys.path.append(FIND_RUNTIME_SYMBOLS_PATH)
22
23 from prepare_symbol_info import prepare_symbol_info
24 from find_runtime_symbols import find_runtime_symbols_list
25
16 BUCKET_ID = 5 26 BUCKET_ID = 5
17 VIRTUAL = 0 27 VIRTUAL = 0
18 COMMITTED = 1 28 COMMITTED = 1
19 ALLOC_COUNT = 2 29 ALLOC_COUNT = 2
20 FREE_COUNT = 3 30 FREE_COUNT = 3
21 NULL_REGEX = re.compile('') 31 NULL_REGEX = re.compile('')
22 32
23 # If an executable pprof script is in the directory of deep_memory_profiler,
24 # use it. Otherwise, use tcmalloc's pprof.
25 #
26 # A pprof script in deep_memory_profiler/ is prioritized to allow packaging
27 # deep_memory_profiler files with a pprof script. The packaged
28 # deep_memory_profiler is downloaded with pprof by using download.sh.
29 PPROF_PATH = os.path.join(os.path.dirname(__file__), 'pprof')
30 if not (os.path.isfile(PPROF_PATH) and os.access(PPROF_PATH, os.X_OK)):
31 PPROF_PATH = os.path.join(os.path.dirname(__file__),
32 os.pardir,
33 os.pardir,
34 'third_party',
35 'tcmalloc',
36 'chromium',
37 'src',
38 'pprof')
39
40 # Heap Profile Dump versions 33 # Heap Profile Dump versions
41 34
42 # DUMP_DEEP_1 is OBSOLETE. 35 # DUMP_DEEP_1 is OBSOLETE.
43 # DUMP_DEEP_1 DOES NOT distinct mmap regions and malloc chunks. 36 # DUMP_DEEP_1 DOES NOT distinct mmap regions and malloc chunks.
44 # Their stacktraces DO contain mmap* or tc-* at their tops. 37 # Their stacktraces DO contain mmap* or tc-* at their tops.
45 # They should be processed by POLICY_DEEP_1. 38 # They should be processed by POLICY_DEEP_1.
46 DUMP_DEEP_1 = 'DUMP_DEEP_1' 39 DUMP_DEEP_1 = 'DUMP_DEEP_1'
47 40
48 # DUMP_DEEP_2 is OBSOLETE. 41 # DUMP_DEEP_2 is OBSOLETE.
49 # DUMP_DEEP_2 DOES distinct mmap regions and malloc chunks. 42 # DUMP_DEEP_2 DOES distinct mmap regions and malloc chunks.
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 557
565 sorted_sizes_list = sorted( 558 sorted_sizes_list = sorted(
566 sizes.iteritems(), key=(lambda x: x[1]), reverse=True) 559 sizes.iteritems(), key=(lambda x: x[1]), reverse=True)
567 total = 0 560 total = 0
568 for size_pair in sorted_sizes_list: 561 for size_pair in sorted_sizes_list:
569 sys.stdout.write('%10d %s\n' % (size_pair[1], size_pair[0])) 562 sys.stdout.write('%10d %s\n' % (size_pair[1], size_pair[0]))
570 total += size_pair[1] 563 total += size_pair[1]
571 sys.stderr.write('total: %d\n' % (total)) 564 sys.stderr.write('total: %d\n' % (total))
572 565
573 566
574 def update_symbols(symbol_path, mapping_lines, chrome_path): 567 def update_symbols(symbol_path, mapping_lines, maps_path):
575 """Updates address/symbol mapping on memory and in a .symbol cache file. 568 """Updates address/symbol mapping on memory and in a .symbol cache file.
576 569
577 It reads cached address/symbol mapping from a .symbol file if it exists. 570 It reads cached address/symbol mapping from a .symbol file if it exists.
578 Then, it resolves unresolved addresses from a Chrome binary with pprof. 571 Then, it resolves unresolved addresses from a Chrome binary with pprof.
579 Both mappings on memory and in a .symbol cache file are updated. 572 Both mappings on memory and in a .symbol cache file are updated.
580 573
581 Symbol files are formatted as follows: 574 Symbol files are formatted as follows:
582 <Address> <Symbol> 575 <Address> <Symbol>
583 <Address> <Symbol> 576 <Address> <Symbol>
584 <Address> <Symbol> 577 <Address> <Symbol>
585 ... 578 ...
586 579
587 Args: 580 Args:
588 symbol_path: A string representing a path for a .symbol file. 581 symbol_path: A string representing a path for a .symbol file.
589 mapping_lines: A list of strings containing /proc/.../maps. 582 mapping_lines: A list of strings containing /proc/.../maps.
590 chrome_path: A string representing a path for a Chrome binary. 583 maps_path: A string of the path of /proc/.../maps.
591 """ 584 """
592 with open(symbol_path, mode='a+') as symbol_f: 585 with open(symbol_path, mode='a+') as symbol_f:
593 symbol_lines = symbol_f.readlines() 586 symbol_lines = symbol_f.readlines()
594 if symbol_lines: 587 if symbol_lines:
595 for line in symbol_lines: 588 for line in symbol_lines:
596 items = line.split(None, 1) 589 items = line.split(None, 1)
597 address_symbol_dict[items[0]] = items[1].rstrip() 590 address_symbol_dict[items[0]] = items[1].rstrip()
598 591
599 unresolved_addresses = sorted( 592 unresolved_addresses = sorted(
600 a for a in appeared_addresses if a not in address_symbol_dict) 593 a for a in appeared_addresses if a not in address_symbol_dict)
601 594
602 if unresolved_addresses: 595 if unresolved_addresses:
603 with tempfile.NamedTemporaryFile( 596 prepared_data_dir = tempfile.mkdtemp()
604 suffix='maps', prefix="dmprof", mode='w+') as pprof_in: 597 prepare_symbol_info(maps_path, prepared_data_dir)
M-A Ruel 2012/07/23 12:01:20 wrap lines 597-606 into try: and line 607 inside f
605 with tempfile.NamedTemporaryFile(
606 suffix='symbols', prefix="dmprof", mode='w+') as pprof_out:
607 for line in mapping_lines:
608 pprof_in.write(line)
609 598
610 for address in unresolved_addresses: 599 symbols = find_runtime_symbols_list(
611 pprof_in.write(address + '\n') 600 prepared_data_dir, unresolved_addresses)
612 601
613 pprof_in.seek(0) 602 for address, symbol in zip(unresolved_addresses, symbols):
603 stripped_symbol = symbol.strip()
604 address_symbol_dict[address] = stripped_symbol
605 symbol_f.write('%s %s\n' % (address, stripped_symbol))
614 606
615 p = subprocess.Popen( 607 shutil.rmtree(prepared_data_dir)
616 '%s --symbols %s' % (PPROF_PATH, chrome_path),
617 shell=True, stdin=pprof_in, stdout=pprof_out)
618 p.wait()
619
620 pprof_out.seek(0)
621 symbols = pprof_out.readlines()
622 symbol_f.seek(0, 2)
623 for address, symbol in zip(unresolved_addresses, symbols):
624 stripped_symbol = symbol.strip()
625 address_symbol_dict[address] = stripped_symbol
626 symbol_f.write('%s %s\n' % (address, symbol.strip()))
627 608
628 609
629 def parse_policy(policy_path): 610 def parse_policy(policy_path):
630 """Parses policy file. 611 """Parses policy file.
631 612
632 A policy file contains component's names and their 613 A policy file contains component's names and their
633 stacktrace pattern written in regular expression. 614 stacktrace pattern written in regular expression.
634 Those patterns are matched against each symbols of 615 Those patterns are matched against each symbols of
635 each stacktraces in the order written in the policy file 616 each stacktraces in the order written in the policy file
636 617
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 new_log.parse_log(buckets) 744 new_log.parse_log(buckets)
764 except EmptyDumpException: 745 except EmptyDumpException:
765 sys.stderr.write(' WARNING: ignored an empty dump: %s\n' % path) 746 sys.stderr.write(' WARNING: ignored an empty dump: %s\n' % path)
766 except ParsingException, e: 747 except ParsingException, e:
767 sys.stderr.write(' Error in parsing heap profile dump: %s\n' % e) 748 sys.stderr.write(' Error in parsing heap profile dump: %s\n' % e)
768 sys.exit(1) 749 sys.exit(1)
769 else: 750 else:
770 logs.append(new_log) 751 logs.append(new_log)
771 752
772 sys.stderr.write('getting symbols\n') 753 sys.stderr.write('getting symbols\n')
773 update_symbols(symbol_path, maps_lines, chrome_path) 754 update_symbols(symbol_path, maps_lines, maps_path)
774 755
775 # TODO(dmikurube): Many modes now. Split them into separete functions. 756 # TODO(dmikurube): Many modes now. Split them into separete functions.
776 if action == '--stacktrace': 757 if action == '--stacktrace':
777 logs[0].dump_stacktrace(buckets) 758 logs[0].dump_stacktrace(buckets)
778 759
779 elif action == '--csv': 760 elif action == '--csv':
780 sys.stdout.write(','.join(components)) 761 sys.stdout.write(','.join(components))
781 sys.stdout.write('\n') 762 sys.stdout.write('\n')
782 763
783 for log in logs: 764 for log in logs:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 803
823 elif action == '--pprof': 804 elif action == '--pprof':
824 if len(sys.argv) > 5: 805 if len(sys.argv) > 5:
825 logs[0].dump_for_pprof(policy_list, buckets, maps_lines, sys.argv[5]) 806 logs[0].dump_for_pprof(policy_list, buckets, maps_lines, sys.argv[5])
826 else: 807 else:
827 logs[0].dump_for_pprof(policy_list, buckets, maps_lines, None) 808 logs[0].dump_for_pprof(policy_list, buckets, maps_lines, None)
828 809
829 810
830 if __name__ == '__main__': 811 if __name__ == '__main__':
831 sys.exit(main()) 812 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/deep_memory_profiler/download.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698