For use in production you are right, we need some benchmarking. Both
memory overhead and startup latency as mentioned by Dominig are
relevant. Do we have tools in Tizen for measuring shared vs. unshared
memory mappings? More specifically, how did you identify the 1.5 MB
number above?

I fixed the Tizen-specific issues that I mentioned in my announcement,
so I can run some benchmarks on a VTC1010 now.

I used simple test script (hello.py):
#! /usr/bin/python

print 'Hello World'
raw_input()


On the second terminal I ran:
top -p $(pgrep hello.py)

I got such results:
PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
2507 root      20   0    5956   3080   1452 S  0.0  0.1   0:00.01 hello.py

RES column denotes how much physical memory given process uses. SHR shows how much physical memory is shareable. I assume that the rest is private to the process (about 1.6 MB). This is consistent with what /proc/<pid>/smaps contains. It gives information such as resident set size and how much memory is shared or private for each mapping. Before I was made aware that /proc/<pid>/smaps contains these useful information I wrote a python script that parses information from /proc/<pid>/maps and /proc/<pid>/pagemap files (attached) and output it shows also confirms figure I talked about.

Best regards,

--
Jacek Bukarewicz
Samsung R&D Institute Poland
Samsung Electronics
[email protected]

#! /usr/bin/python
# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License

import subprocess
import struct
import argparse

def get_vmem_region(range_string):
    virtual_memory_region=range_string.split("-")
    start=int(virtual_memory_region[0], 16)
    end=int(virtual_memory_region[1], 16)
    return (start, end)

def page_info_range(pagemap_file, virtual_pfn_start, virtual_pfn_end):
    for pfn in xrange(virtual_pfn_start, virtual_pfn_end):
        pagemap_file.seek(8*pfn)
        tmp=pagemap_file.read(8)
        if (len(tmp) == 8):   # reading pagemap file fails for [vsyscall] region
            page_info=struct.unpack('Q', tmp)
            yield pfn, page_info[0]

# heap or stack(s)
def is_data(map_line_parsed):
    return len(map_line_parsed) == 6 and (map_line_parsed[5].startswith('[stack') or \
        map_line_parsed[5] == '[heap]')


def is_anonymous(map_line_parsed):
    return len(map_line_parsed) < 6 or map_line_parsed[5].startswith('/dev/zero')

def print_map_info():
    with open(proc_maps_path) as f:
        proc_maps = f.readlines()
    
    virt_total=0
    phys_total=0
    
    virt_data_total=0
    phys_data_total=0
    
    swapped_total=0
    data_swapped_total=0
    
    phys_shared_total=0
    phys_private_total=0
    
    phys_anon_total=0
    
    print "%025s %06s %08s %05s %8s  %8s  %6s  %4s  %4s      %s" % ('VIRTUAL ADDRESS RANGE', \
          'PERMS', 'OFFSET', 'DEV', 'INODE', 'VIRT', 'PHYS', 'SHR', 'PRIV', 'PATHNAME')
    with open(proc_pagemap_path) as f:
        for map_line in proc_maps:
            map_line_parsed = map_line.split()
            
            vmem_region = get_vmem_region(map_line_parsed[0])
            virt_pfn_start = vmem_region[0]/page_size
            virt_pfn_end = vmem_region[1]/page_size
            virt_size = vmem_region[1] - vmem_region[0]
    
            phys_pages_count = 0
            swapped_count = 0
            shared_pages_count = 0
            private_pages_count = 0
            
            for virt_pfn, page_info in page_info_range(f, virt_pfn_start, virt_pfn_end):
                if page_info & (0x3 << 62): # 'page present' or 'page swapped' bit set
                    phys_pages_count += 1
                    if page_info & (0x1 << 62): # 'page swapped' bit set
                        swapped_count += 1
                    if (page_info & (0x1 << 61)): # 'page is file-page or shared-anon' (kernel >= 3.5) 
                        shared_pages_count += 1
                    else:
                        private_pages_count += 1
            
            phys_size = page_size*phys_pages_count
            swapped_size = page_size*swapped_count
            
            virt_total += virt_size
            phys_total += phys_size
            swapped_total += swapped_size
    
            shared_size = shared_pages_count*page_size
            phys_shared_total += shared_size
            
            private_size = private_pages_count*page_size
            phys_private_total += private_size
            
            if is_data(map_line_parsed):
                virt_data_total += virt_size
                phys_data_total += phys_size
                data_swapped_total += swapped_size
            if is_anonymous(map_line_parsed):
                phys_anon_total += phys_size
            path = ''
            if len(map_line_parsed) >= 6:
                path=map_line_parsed[5]
            print "%025s %06s %08s %05s %8s %8dK %6dK %4dK %4dK      %s" % (map_line_parsed[0],
                                          map_line_parsed[1], map_line_parsed[2],
                                          map_line_parsed[3], map_line_parsed[4],virt_size/1024,
                                          phys_size/1024, shared_size/1024, private_size/1024,
                                           path)
    
    print 
    print 'Virtual memory:'
    print '  Total:                %dK' % (virt_total/1024)
    print
    print 'Physical memory:'
    
    print '  Total:                %dK' % (phys_total/1024)
    print '  Swapped:              %dK' % (swapped_total/1024)
    print '  Shared:               %dK' % (phys_shared_total/1024)
    print '  Private:              %dK' % (phys_private_total/1024)
    print '  Heap + stacks:        %dK' % (phys_data_total/1024)
    print '  Anonymous mappings:   %dK' % (phys_anon_total/1024)
    
def dump_mmu_mappings(virt_pfn_start, virt_pfn_end):
    with open(proc_pagemap_path) as f:
        for virt_pfn, page_info in page_info_range(f, virt_pfn_start, virt_pfn_end):
            if page_info & (0x1 << 62):
                print "%012X -> (swapped)" % (virt_pfn*page_size)
            else:
                phys_pfn = page_info & ((0x1 << 55) - 1)
                print "%012X -> %010X " % (virt_pfn*page_size, phys_pfn*page_size)
            
def print_interactive_commands():
    print 'q - quit'
    print 'r - refresh'
    print 'd virt_start-virt_end - dump MMU mappings for the given virtual address range'

def process_commands():
    while True:
        
        line = raw_input()
        parsed = line.split()
        
        if len(parsed) > 0:
            if parsed[0] == 'q':
                break
            elif parsed[0] == 'r':
                print_map_info()
                continue
            elif parsed[0] == 'd':
                if len(parsed) == 2:
                    vmem_range=get_vmem_region(parsed[1])
                    dump_mmu_mappings(int(vmem_range[0])/page_size, int(vmem_range[1])/page_size)
                    continue
        print_interactive_commands()

if __name__ == "__main__":
    interactive = True
    parser = argparse.ArgumentParser(description='Print detailed memory mappings for given process')
    parser.add_argument('-n', action='store_true', help='non-interactive mode')
    parser.add_argument('pid', help='process id')
    args = parser.parse_args()
    if args.n:
        interactive = False

    pid = args.pid

    page_size = int(subprocess.check_output(['getconf', 'PAGESIZE']))
    
    proc_maps_path = '/proc/' + pid + '/maps'
    proc_pagemap_path = '/proc/' + pid + '/pagemap'
    
    print_map_info()
    if interactive:
        print
        print_interactive_commands()
        process_commands()
_______________________________________________
Dev mailing list
[email protected]
https://lists.tizen.org/listinfo/dev

Reply via email to