#!/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()

#!/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()

#!/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. takes key-value pairs contained in string 	and returns a dictionary of KVP's returns the percentage, or zero if denominator 	is zero class for "counters" to simply 	incrementing and retrieving values