227 lines
7.9 KiB
Python
227 lines
7.9 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
# Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||
|
#
|
||
|
# Redistribution and use in source and binary forms, with or without
|
||
|
# modification, are permitted provided that the following conditions are
|
||
|
# met:
|
||
|
# * Redistributions of source code must retain the above copyright
|
||
|
# notice, this list of conditions and the following disclaimer.
|
||
|
# * Redistributions in binary form must reproduce the above
|
||
|
# copyright notice, this list of conditions and the following
|
||
|
# disclaimer in the documentation and/or other materials provided
|
||
|
# with the distribution.
|
||
|
# * Neither the name of The Linux Foundation nor the names of its
|
||
|
# contributors may be used to endorse or promote products derived
|
||
|
# from this software without specific prior written permission.
|
||
|
#
|
||
|
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||
|
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||
|
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||
|
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||
|
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||
|
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||
|
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
import string
|
||
|
import re
|
||
|
|
||
|
def create_dict(str):
|
||
|
"""
|
||
|
takes key-value pairs contained in string
|
||
|
and returns a dictionary of KVP's
|
||
|
"""
|
||
|
return dict(re.findall(r'(\S+)=(\S+)', str))
|
||
|
|
||
|
def return_ratio(prop, total):
|
||
|
"""
|
||
|
returns the percentage, or zero if denominator
|
||
|
is zero
|
||
|
"""
|
||
|
return str(round(((float(prop)/float(total))
|
||
|
*100), 3)) if (total != 0) else str(0)
|
||
|
|
||
|
class Incrementor(object):
|
||
|
"""
|
||
|
class for "counters" to simply
|
||
|
incrementing and retrieving values
|
||
|
"""
|
||
|
def __init__(self, start):
|
||
|
self.count=start
|
||
|
def __call__(self, jump=1):
|
||
|
self.count += jump
|
||
|
return self.count
|
||
|
|
||
|
class MapEntry(object):
|
||
|
def __init__(self, vals):
|
||
|
self.v_addr=vals['v_addr']
|
||
|
self.p_addr=vals['p_addr']
|
||
|
self.chunk_size=vals['chunk_size']
|
||
|
self.length=int(vals['len'])
|
||
|
|
||
|
class AllocEntry(object):
|
||
|
def __init__(self, vals):
|
||
|
self.gfp_flags=vals['gfp_flags']
|
||
|
self.order=int(vals['order'])
|
||
|
|
||
|
class MapStat(object):
|
||
|
def __init__(self):
|
||
|
self.total_calls = Incrementor(0)
|
||
|
self.size_sixteenm = Incrementor(0)
|
||
|
self.size_onem = Incrementor(0)
|
||
|
self.size_sixtyfourk = Incrementor(0)
|
||
|
self.size_fourk = Incrementor(0)
|
||
|
def total(self):
|
||
|
return str(self.total_calls(0))
|
||
|
def SM(self):
|
||
|
return str(self.size_sixteenm(0))
|
||
|
def OM(self):
|
||
|
return str(self.size_onem(0))
|
||
|
def SFK(self):
|
||
|
return str(self.size_sixtyfourk(0))
|
||
|
def fk(self):
|
||
|
return str(self.size_fourk(0))
|
||
|
def SM_ratio(self):
|
||
|
return return_ratio(self.size_sixteenm(0), self.total_calls(0))
|
||
|
def OM_ratio(self):
|
||
|
return return_ratio(self.size_onem(0), self.total_calls(0))
|
||
|
def SFK_ratio(self):
|
||
|
return return_ratio(self.size_sixtyfourk(0), self.total_calls(0))
|
||
|
def fk_ratio(self):
|
||
|
return return_ratio(self.size_fourk(0), self.total_calls(0))
|
||
|
|
||
|
class AllocStat(object):
|
||
|
def __init__(self):
|
||
|
self.total_heap_alloc_calls = Incrementor(0)
|
||
|
self.failed_heap_allocs = Incrementor(0)
|
||
|
self.heap_alloc_order_zero = Incrementor(0)
|
||
|
self.heap_alloc_order_four = Incrementor(0)
|
||
|
self.heap_alloc_order_eight = Incrementor(0)
|
||
|
def total(self):
|
||
|
return str(self.total_heap_alloc_calls(0))
|
||
|
def fail(self):
|
||
|
return str(self.failed_heap_allocs(0))
|
||
|
def zero(self):
|
||
|
return str(self.heap_alloc_order_zero(0))
|
||
|
def four(self):
|
||
|
return str(self.heap_alloc_order_four(0))
|
||
|
def eight(self):
|
||
|
return str(self.heap_alloc_order_eight(0))
|
||
|
def fail_ratio(self):
|
||
|
return return_ratio(self.failed_heap_allocs(0), self.total_heap_alloc_calls(0))
|
||
|
def zero_ratio(self):
|
||
|
return return_ratio(self.heap_alloc_order_zero(0), self.total_heap_alloc_calls(0))
|
||
|
def four_ratio(self):
|
||
|
return return_ratio(self.heap_alloc_order_four(0), self.total_heap_alloc_calls(0))
|
||
|
def eight_ratio(self):
|
||
|
return return_ratio(self.heap_alloc_order_eight(0), self.total_heap_alloc_calls(0))
|
||
|
|
||
|
class Stats(object):
|
||
|
def __init__(self):
|
||
|
self.map_calls = MapStat()
|
||
|
self.iommu = AllocStat()
|
||
|
self.sys = AllocStat()
|
||
|
with open('trace', 'r') as trace_file:
|
||
|
for line in trace_file:
|
||
|
self.process_line(line)
|
||
|
|
||
|
def process_line(self, line):
|
||
|
index=string.find(line, "iommu_map_range:")
|
||
|
if index >= 0:
|
||
|
return self.iommu_map_range(create_dict(line))
|
||
|
index=string.find(line, "alloc_pages_iommu_start:")
|
||
|
if index >= 0:
|
||
|
return self.alloc_pages_iommu_start(create_dict(line))
|
||
|
index=string.find(line, "alloc_pages_iommu_fail:")
|
||
|
if index >= 0:
|
||
|
return self.alloc_pages_iommu_fail(create_dict(line))
|
||
|
index=string.find(line, "alloc_pages_sys_start:")
|
||
|
if index >= 0:
|
||
|
return self.alloc_pages_sys_start(create_dict(line))
|
||
|
index=string.find(line, "alloc_pages_sys_fail:")
|
||
|
if index >= 0:
|
||
|
return self.alloc_pages_sys_fail(create_dict(line))
|
||
|
|
||
|
def iommu_map_range(self, vals):
|
||
|
stat = MapEntry(vals)
|
||
|
self.map_calls.total_calls()
|
||
|
if stat.length==(1 << 24):
|
||
|
self.map_calls.size_sixteenm()
|
||
|
elif stat.length==(1 << 20):
|
||
|
self.map_calls.size_onem()
|
||
|
elif stat.length==(1 << 16):
|
||
|
self.map_calls.size_sixtyfourk()
|
||
|
elif stat.length==(1 << 12):
|
||
|
self.map_calls.size_fourk()
|
||
|
else:
|
||
|
print "Unsupported Length: " + str(stat.length)
|
||
|
|
||
|
def alloc_pages_iommu_start(self, vals):
|
||
|
stat = AllocEntry(vals)
|
||
|
self.iommu.total_heap_alloc_calls()
|
||
|
if stat.order == 0:
|
||
|
self.iommu.heap_alloc_order_zero()
|
||
|
elif stat.order == 4:
|
||
|
self.iommu.heap_alloc_order_four()
|
||
|
elif stat.order == 8:
|
||
|
self.iommu.heap_alloc_order_eight()
|
||
|
else:
|
||
|
print "Unsupported Order: " + str(stat.order)
|
||
|
|
||
|
def alloc_pages_iommu_fail(self, vals):
|
||
|
stat = AllocEntry(vals)
|
||
|
self.iommu.failed_heap_allocs()
|
||
|
|
||
|
def alloc_pages_sys_start(self, vals):
|
||
|
stat = AllocEntry(vals)
|
||
|
self.sys.total_heap_alloc_calls()
|
||
|
if stat.order == 0:
|
||
|
self.sys.heap_alloc_order_zero()
|
||
|
elif stat.order == 4:
|
||
|
self.sys.heap_alloc_order_four()
|
||
|
else:
|
||
|
self.sys.heap_alloc_order_eight()
|
||
|
|
||
|
def alloc_pages_sys_fail(self, vals):
|
||
|
stat = AllocEntry(vals)
|
||
|
self.sys.failed_heap_allocs()
|
||
|
|
||
|
def return_results(self):
|
||
|
print ''.join(["Total Calls to Map Range: ", self.map_calls.total()])
|
||
|
print ''.join(["Mapped Pages of Size 16MB: ",
|
||
|
self.map_calls.SM(), "(", self.map_calls.SM_ratio(), "%)"])
|
||
|
print ''.join(["Mapped Pages of Size 1MB: ",
|
||
|
self.map_calls.OM(), "(", self.map_calls.OM_ratio(), "%)"])
|
||
|
print ''.join(["Mapped Pages of Size 64KB: ",
|
||
|
self.map_calls.SFK(), "(", self.map_calls.SFK_ratio(), "%)"])
|
||
|
print ''.join(["Mapped Pages of Size 4KB: ",
|
||
|
self.map_calls.fk(), "(", self.map_calls.fk_ratio(), "%)"])
|
||
|
print "---"
|
||
|
print ''.join(["Total Calls to Alloc in iommu Heap: ", self.iommu.total()])
|
||
|
print ''.join(["Failed iommu Heap Allocations: ",
|
||
|
self.iommu.fail(),"(", self.iommu.fail_ratio(),"%)"])
|
||
|
print ''.join(["iommu Heap Allocations of Order Zero: ",
|
||
|
self.iommu.zero(), "(", self.iommu.zero_ratio(), "%)"])
|
||
|
print ''.join(["iommu Heap Allocations of Order Four: ",
|
||
|
self.iommu.four(), "(", self.iommu.four_ratio(), "%)"])
|
||
|
print ''.join(["iommu Heap Allocations of Order Eight: ",
|
||
|
self.iommu.eight(), "(", self.iommu.eight_ratio(), "%)"])
|
||
|
print "---"
|
||
|
print ''.join(["Total Calls to Alloc in sys Heap: ", self.sys.total()])
|
||
|
print ''.join(["Failed sys Heap Allocations: ",
|
||
|
self.sys.fail(),"(", self.sys.fail_ratio(),"%)"])
|
||
|
print ''.join(["sys Heap Allocations of Order Zero: ",
|
||
|
self.sys.zero(), "(", self.sys.zero_ratio(), "%)"])
|
||
|
print ''.join(["sys Heap Allocations of Order Four: ",
|
||
|
self.sys.four(), "(", self.sys.four_ratio(), "%)"])
|
||
|
print ''.join(["sys Heap Allocations of Order Eight: ",
|
||
|
self.sys.eight(), "(", self.sys.eight_ratio(), "%)"])
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
stat = Stats()
|
||
|
stat.return_results()
|