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

Side by Side Diff: tools/linux/procfs.py

Issue 98423003: Resident set size (RSS) of multiple processes without double-counts on Linux. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years 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/multi-process-rss.py » ('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 2013 The Chromium Authors. All rights reserved. 2 # Copyright 2013 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 # A Python library to read and store procfs (/proc) information on Linux. 6 # A Python library to read and store procfs (/proc) information on Linux.
7 # 7 #
8 # Each information storage class in this file stores original data as original 8 # Each information storage class in this file stores original data as original
9 # as reasonablly possible. Translation is done when requested. It is to make it 9 # as reasonablly possible. Translation is done when requested. It is to make it
10 # always possible to probe the original data. 10 # always possible to probe the original data.
11 11
12 12
13 import collections 13 import collections
14 import logging 14 import logging
15 import os 15 import os
16 import re 16 import re
17 import struct 17 import struct
18 import sys 18 import sys
19 19
20 20
21 LOGGER = logging.getLogger('procfs') 21 class _NullHandler(logging.Handler):
22 def emit(self, record):
23 pass
24
25
26 _LOGGER = logging.getLogger('procfs')
27 _LOGGER.addHandler(_NullHandler())
22 28
23 29
24 class ProcStat(object): 30 class ProcStat(object):
25 """Reads and stores information in /proc/pid/stat.""" 31 """Reads and stores information in /proc/pid/stat."""
26 _PATTERN = re.compile(r'^' 32 _PATTERN = re.compile(r'^'
27 '(?P<PID>-?[0-9]+) ' 33 '(?P<PID>-?[0-9]+) '
28 '\((?P<COMM>.+)\) ' 34 '\((?P<COMM>.+)\) '
29 '(?P<STATE>[RSDZTW]) ' 35 '(?P<STATE>[RSDZTW]) '
30 '(?P<PPID>-?[0-9]+) ' 36 '(?P<PPID>-?[0-9]+) '
31 '(?P<PGRP>-?[0-9]+) ' 37 '(?P<PGRP>-?[0-9]+) '
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 self._vma_internals = vma_internals 546 self._vma_internals = vma_internals
541 self._in_process_dup = in_process_dup 547 self._in_process_dup = in_process_dup
542 548
543 @staticmethod 549 @staticmethod
544 def load(pid, maps): 550 def load(pid, maps):
545 total_present = 0 551 total_present = 0
546 total_swapped = 0 552 total_swapped = 0
547 total_vsize = 0 553 total_vsize = 0
548 in_process_dup = 0 554 in_process_dup = 0
549 vma_internals = collections.OrderedDict() 555 vma_internals = collections.OrderedDict()
556 process_pageframe_set = set()
550 557
551 pagemap_fd = os.open( 558 pagemap_fd = os.open(
552 os.path.join('/proc', str(pid), 'pagemap'), os.O_RDONLY) 559 os.path.join('/proc', str(pid), 'pagemap'), os.O_RDONLY)
553 for vma in maps: 560 for vma in maps:
554 present = 0 561 present = 0
555 swapped = 0 562 swapped = 0
556 vsize = 0 563 vsize = 0
557 pageframes = collections.defaultdict(int) 564 pageframes = collections.defaultdict(int)
558 pageframes_set = set()
559 begin_offset = ProcPagemap._offset(vma.begin) 565 begin_offset = ProcPagemap._offset(vma.begin)
560 chunk_size = ProcPagemap._offset(vma.end) - begin_offset 566 chunk_size = ProcPagemap._offset(vma.end) - begin_offset
561 os.lseek(pagemap_fd, begin_offset, os.SEEK_SET) 567 os.lseek(pagemap_fd, begin_offset, os.SEEK_SET)
562 buf = os.read(pagemap_fd, chunk_size) 568 buf = os.read(pagemap_fd, chunk_size)
563 if len(buf) < chunk_size: 569 if len(buf) < chunk_size:
564 LOGGER.warn('Failed to read pagemap at 0x%x.' % vma.begin) 570 _LOGGER.warn('Failed to read pagemap at 0x%x in %d.' % (vma.begin, pid))
565 pagemap_values = struct.unpack( 571 pagemap_values = struct.unpack(
566 '=%dQ' % (len(buf) / ProcPagemap._BYTES_PER_PAGEMAP_VALUE), buf) 572 '=%dQ' % (len(buf) / ProcPagemap._BYTES_PER_PAGEMAP_VALUE), buf)
567 for pagemap_value in pagemap_values: 573 for pagemap_value in pagemap_values:
568 vsize += ProcPagemap._BYTES_PER_OS_PAGE 574 vsize += ProcPagemap._BYTES_PER_OS_PAGE
569 if pagemap_value & ProcPagemap._MASK_PRESENT: 575 if pagemap_value & ProcPagemap._MASK_PRESENT:
570 if (pagemap_value & ProcPagemap._MASK_PFN) in pageframes_set: 576 if (pagemap_value & ProcPagemap._MASK_PFN) in process_pageframe_set:
571 in_process_dup += ProcPagemap._BYTES_PER_OS_PAGE 577 in_process_dup += ProcPagemap._BYTES_PER_OS_PAGE
572 else: 578 else:
573 pageframes_set.add(pagemap_value & ProcPagemap._MASK_PFN) 579 process_pageframe_set.add(pagemap_value & ProcPagemap._MASK_PFN)
574 if (pagemap_value & ProcPagemap._MASK_PFN) not in pageframes: 580 if (pagemap_value & ProcPagemap._MASK_PFN) not in pageframes:
575 present += ProcPagemap._BYTES_PER_OS_PAGE 581 present += ProcPagemap._BYTES_PER_OS_PAGE
576 pageframes[pagemap_value & ProcPagemap._MASK_PFN] += 1 582 pageframes[pagemap_value & ProcPagemap._MASK_PFN] += 1
577 if pagemap_value & ProcPagemap._MASK_SWAPPED: 583 if pagemap_value & ProcPagemap._MASK_SWAPPED:
578 swapped += ProcPagemap._BYTES_PER_OS_PAGE 584 swapped += ProcPagemap._BYTES_PER_OS_PAGE
579 vma_internals[vma] = ProcPagemap.VMA(vsize, present, swapped, pageframes) 585 vma_internals[vma] = ProcPagemap.VMA(vsize, present, swapped, pageframes)
580 total_present += present 586 total_present += present
581 total_swapped += swapped 587 total_swapped += swapped
582 total_vsize += vsize 588 total_vsize += vsize
583 os.close(pagemap_fd) 589 os.close(pagemap_fd)
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 def statm(self): 679 def statm(self):
674 return self._statm 680 return self._statm
675 681
676 @property 682 @property
677 def status(self): 683 def status(self):
678 return self._status 684 return self._status
679 685
680 686
681 def main(argv): 687 def main(argv):
682 """The main function for manual testing.""" 688 """The main function for manual testing."""
683 689 _LOGGER.setLevel(logging.WARNING)
684 LOGGER.setLevel(logging.DEBUG)
685 handler = logging.StreamHandler() 690 handler = logging.StreamHandler()
686 handler.setLevel(logging.INFO) 691 handler.setLevel(logging.WARNING)
687 formatter = logging.Formatter('%(message)s') 692 handler.setFormatter(logging.Formatter(
688 handler.setFormatter(formatter) 693 '%(asctime)s:%(name)s:%(levelname)s:%(message)s'))
689 LOGGER.addHandler(handler) 694 _LOGGER.addHandler(handler)
690 695
691 pids = [] 696 pids = []
692 for arg in argv[1:]: 697 for arg in argv[1:]:
693 try: 698 try:
694 pid = int(arg) 699 pid = int(arg)
695 except ValueError: 700 except ValueError:
696 raise SyntaxError("%s is not an integer." % arg) 701 raise SyntaxError("%s is not an integer." % arg)
697 else: 702 else:
698 pids.append(pid) 703 pids.append(pid)
699 704
(...skipping 15 matching lines...) Expand all
715 print ' status: %d (Peak:%d)' % (procs[pid].status.vm_rss * 1024, 720 print ' status: %d (Peak:%d)' % (procs[pid].status.vm_rss * 1024,
716 procs[pid].status.vm_hwm * 1024) 721 procs[pid].status.vm_hwm * 1024)
717 print ' smaps: %d' % (procs[pid].smaps.rss * 1024) 722 print ' smaps: %d' % (procs[pid].smaps.rss * 1024)
718 print 'pagemap: %d' % procs[pid].pagemap.present 723 print 'pagemap: %d' % procs[pid].pagemap.present
719 724
720 return 0 725 return 0
721 726
722 727
723 if __name__ == '__main__': 728 if __name__ == '__main__':
724 sys.exit(main(sys.argv)) 729 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | tools/multi-process-rss.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698