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

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: ready for review 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 subprocess 12 import subprocess
13 import sys 13 import sys
14 import tempfile 14 import tempfile
15 15
16 FIND_RUNTIME_SYMBOLS_PATH = os.path.join(os.path.dirname(__file__),
M-A Ruel 2012/07/22 19:51:07 os.path.dirname(os.path.abspath(__file__)) is safe
Dai Mikurube (NOT FULLTIME) 2012/07/23 00:48:45 Done.
17 os.pardir,
18 'find_runtime_symbols')
19 sys.path.append(FIND_RUNTIME_SYMBOLS_PATH)
20
21 from prepare_symbol_info import prepare_symbol_info
22 from find_runtime_symbols import find_runtime_symbols_list
23
16 BUCKET_ID = 5 24 BUCKET_ID = 5
17 VIRTUAL = 0 25 VIRTUAL = 0
18 COMMITTED = 1 26 COMMITTED = 1
19 ALLOC_COUNT = 2 27 ALLOC_COUNT = 2
20 FREE_COUNT = 3 28 FREE_COUNT = 3
21 NULL_REGEX = re.compile('') 29 NULL_REGEX = re.compile('')
22 30
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 31 # Heap Profile Dump versions
41 32
42 # DUMP_DEEP_1 is OBSOLETE. 33 # DUMP_DEEP_1 is OBSOLETE.
43 # DUMP_DEEP_1 DOES NOT distinct mmap regions and malloc chunks. 34 # DUMP_DEEP_1 DOES NOT distinct mmap regions and malloc chunks.
44 # Their stacktraces DO contain mmap* or tc-* at their tops. 35 # Their stacktraces DO contain mmap* or tc-* at their tops.
45 # They should be processed by POLICY_DEEP_1. 36 # They should be processed by POLICY_DEEP_1.
46 DUMP_DEEP_1 = 'DUMP_DEEP_1' 37 DUMP_DEEP_1 = 'DUMP_DEEP_1'
47 38
48 # DUMP_DEEP_2 is OBSOLETE. 39 # DUMP_DEEP_2 is OBSOLETE.
49 # DUMP_DEEP_2 DOES distinct mmap regions and malloc chunks. 40 # DUMP_DEEP_2 DOES distinct mmap regions and malloc chunks.
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 554
564 sorted_sizes_list = sorted( 555 sorted_sizes_list = sorted(
565 sizes.iteritems(), key=(lambda x: x[1]), reverse=True) 556 sizes.iteritems(), key=(lambda x: x[1]), reverse=True)
566 total = 0 557 total = 0
567 for size_pair in sorted_sizes_list: 558 for size_pair in sorted_sizes_list:
568 sys.stdout.write('%10d %s\n' % (size_pair[1], size_pair[0])) 559 sys.stdout.write('%10d %s\n' % (size_pair[1], size_pair[0]))
569 total += size_pair[1] 560 total += size_pair[1]
570 sys.stderr.write('total: %d\n' % (total)) 561 sys.stderr.write('total: %d\n' % (total))
571 562
572 563
573 def update_symbols(symbol_path, mapping_lines, chrome_path): 564 def update_symbols(symbol_path, mapping_lines, maps_path):
574 """Updates address/symbol mapping on memory and in a .symbol cache file. 565 """Updates address/symbol mapping on memory and in a .symbol cache file.
575 566
576 It reads cached address/symbol mapping from a .symbol file if it exists. 567 It reads cached address/symbol mapping from a .symbol file if it exists.
577 Then, it resolves unresolved addresses from a Chrome binary with pprof. 568 Then, it resolves unresolved addresses from a Chrome binary with pprof.
578 Both mappings on memory and in a .symbol cache file are updated. 569 Both mappings on memory and in a .symbol cache file are updated.
579 570
580 Symbol files are formatted as follows: 571 Symbol files are formatted as follows:
581 <Address> <Symbol> 572 <Address> <Symbol>
582 <Address> <Symbol> 573 <Address> <Symbol>
583 <Address> <Symbol> 574 <Address> <Symbol>
584 ... 575 ...
585 576
586 Args: 577 Args:
587 symbol_path: A string representing a path for a .symbol file. 578 symbol_path: A string representing a path for a .symbol file.
588 mapping_lines: A list of strings containing /proc/.../maps. 579 mapping_lines: A list of strings containing /proc/.../maps.
589 chrome_path: A string representing a path for a Chrome binary. 580 maps_path: A string of the path of /proc/.../maps.
590 """ 581 """
582 prepared_data_dir = tempfile.mkdtemp()
M-A Ruel 2012/07/22 19:49:06 Is it wanted that this directory is leaked?
Dai Mikurube (NOT FULLTIME) 2012/07/23 00:48:45 Ah, no. Moved these calls and used shutil.rmtree.
583 prepare_symbol_info(maps_path, prepared_data_dir)
584
591 with open(symbol_path, mode='a+') as symbol_f: 585 with open(symbol_path, mode='a+') as symbol_f:
592 symbol_lines = symbol_f.readlines() 586 symbol_lines = symbol_f.readlines()
593 if symbol_lines: 587 if symbol_lines:
594 for line in symbol_lines: 588 for line in symbol_lines:
595 items = line.split(None, 1) 589 items = line.split(None, 1)
596 address_symbol_dict[items[0]] = items[1].rstrip() 590 address_symbol_dict[items[0]] = items[1].rstrip()
597 591
598 unresolved_addresses = sorted( 592 unresolved_addresses = sorted(
599 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)
600 594
601 if unresolved_addresses: 595 if unresolved_addresses:
602 with tempfile.NamedTemporaryFile( 596 symbols = find_runtime_symbols_list(
603 suffix='maps', prefix="dmprof", mode='w+') as pprof_in: 597 prepared_data_dir, unresolved_addresses)
604 with tempfile.NamedTemporaryFile(
605 suffix='symbols', prefix="dmprof", mode='w+') as pprof_out:
606 for line in mapping_lines:
607 pprof_in.write(line)
608 598
609 for address in unresolved_addresses: 599 for address, symbol in zip(unresolved_addresses, symbols):
610 pprof_in.write(address + '\n') 600 stripped_symbol = symbol.strip()
611 601 address_symbol_dict[address] = stripped_symbol
612 pprof_in.seek(0) 602 symbol_f.write('%s %s\n' % (address, symbol.strip()))
M-A Ruel 2012/07/22 19:51:07 I don't see why you are making a local variable an
Dai Mikurube (NOT FULLTIME) 2012/07/23 00:48:45 Done.
613
614 p = subprocess.Popen(
615 '%s --symbols %s' % (PPROF_PATH, chrome_path),
616 shell=True, stdin=pprof_in, stdout=pprof_out)
617 p.wait()
618
619 pprof_out.seek(0)
620 symbols = pprof_out.readlines()
621 symbol_f.seek(0, 2)
622 for address, symbol in zip(unresolved_addresses, symbols):
623 stripped_symbol = symbol.strip()
624 address_symbol_dict[address] = stripped_symbol
625 symbol_f.write('%s %s\n' % (address, symbol.strip()))
626 603
627 604
628 def parse_policy(policy_path): 605 def parse_policy(policy_path):
629 """Parses policy file. 606 """Parses policy file.
630 607
631 A policy file contains component's names and their 608 A policy file contains component's names and their
632 stacktrace pattern written in regular expression. 609 stacktrace pattern written in regular expression.
633 Those patterns are matched against each symbols of 610 Those patterns are matched against each symbols of
634 each stacktraces in the order written in the policy file 611 each stacktraces in the order written in the policy file
635 612
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 new_log.parse_log(buckets) 739 new_log.parse_log(buckets)
763 except EmptyDumpException: 740 except EmptyDumpException:
764 sys.stderr.write(' WARNING: ignored an empty dump: %s\n' % path) 741 sys.stderr.write(' WARNING: ignored an empty dump: %s\n' % path)
765 except ParsingException, e: 742 except ParsingException, e:
766 sys.stderr.write(' Error in parsing heap profile dump: %s\n' % e) 743 sys.stderr.write(' Error in parsing heap profile dump: %s\n' % e)
767 sys.exit(1) 744 sys.exit(1)
768 else: 745 else:
769 logs.append(new_log) 746 logs.append(new_log)
770 747
771 sys.stderr.write('getting symbols\n') 748 sys.stderr.write('getting symbols\n')
772 update_symbols(symbol_path, maps_lines, chrome_path) 749 update_symbols(symbol_path, maps_lines, maps_path)
773 750
774 # TODO(dmikurube): Many modes now. Split them into separete functions. 751 # TODO(dmikurube): Many modes now. Split them into separete functions.
775 if action == '--stacktrace': 752 if action == '--stacktrace':
776 logs[0].dump_stacktrace(buckets) 753 logs[0].dump_stacktrace(buckets)
777 754
778 elif action == '--csv': 755 elif action == '--csv':
779 sys.stdout.write(','.join(components)) 756 sys.stdout.write(','.join(components))
780 sys.stdout.write('\n') 757 sys.stdout.write('\n')
781 758
782 for log in logs: 759 for log in logs:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 798
822 elif action == '--pprof': 799 elif action == '--pprof':
823 if len(sys.argv) > 5: 800 if len(sys.argv) > 5:
824 logs[0].dump_for_pprof(policy_list, buckets, maps_lines, sys.argv[5]) 801 logs[0].dump_for_pprof(policy_list, buckets, maps_lines, sys.argv[5])
825 else: 802 else:
826 logs[0].dump_for_pprof(policy_list, buckets, maps_lines, None) 803 logs[0].dump_for_pprof(policy_list, buckets, maps_lines, None)
827 804
828 805
829 if __name__ == '__main__': 806 if __name__ == '__main__':
830 sys.exit(main()) 807 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