blob: a1f5470b5c9364a450b55cf319f4d900043a43f8 [file] [log] [blame]
from lnt.util import logger
from .profile import ProfileImpl
from .profilev1impl import ProfileV1
import os
import traceback
import glob
try:
from . import cPerf # type: ignore # mypy cannot process Cython modules
except Exception:
pass
def merge_recursively(dct1, dct2):
# type: (dict, dict) -> None
"""Add the content of dct2 to dct1.
:param dct1: merge to.
:param dct2: merge from.
"""
for k, v in dct2.items():
if k in dct1:
if isinstance(dct1[k], dict) and isinstance(v, dict):
merge_recursively(dct1[k], v)
elif isinstance(dct1[k], list) and isinstance(v, list):
dct1[k].extend(v)
else:
raise TypeError("Values for the key {} must be the same type (dict or list), "
"but got {} and {}".format(k, type(dct1[k]), type(v)))
else:
dct1[k] = v
class LinuxPerfProfile(ProfileImpl):
def __init__(self):
pass
@staticmethod
def checkFile(fn):
with open(fn, 'rb') as f:
return f.read(8) == b'PERFILE2'
@staticmethod
def deserialize(f, objdump='objdump', propagateExceptions=False,
binaryCacheRoot=''):
f = f.name
if os.path.getsize(f) == 0:
# Empty file - exit early.
return None
try:
data = {}
for fname in glob.glob("%s*" % f):
cur_data = cPerf.importPerf(fname, objdump, binaryCacheRoot)
merge_recursively(data, cur_data)
# Go through the data and convert counter values to percentages.
for f in data['functions'].values():
fc = f['counters']
for inst_info in f['data']:
for k, v in inst_info[0].items():
inst_info[0][k] = 100.0 * float(v) / fc[k]
for k, v in fc.items():
fc[k] = 100.0 * v / data['counters'][k]
return ProfileV1(data)
except Exception:
if propagateExceptions:
raise
logger.warning(traceback.format_exc())
return None