def generic_profile_provider(profile, of_key, per_key, **_): """Data provider for trace collector profiling output. :param dict profile: the trace profile dictionary :param str of_key: key for which we are finding the model :param str per_key: key of the independent variable :param dict _: rest of the key arguments :returns generator: each subsequent call returns tuple: x points list, y points list, function name """ # Get the file resources contents resources = list(map(itemgetter(1), query.all_resources_of(profile))) # Sort the dictionaries by function name for easier traversing resources = sorted(resources, key=resource_sort_key) x_points_list = [] y_points_list = [] function_name = convert.flatten(resources[0]['uid']) # Store all the points until the function name changes for resource in resources: if convert.flatten(resource['uid']) != function_name: if x_points_list: # Function name changed, yield the list of data points yield x_points_list, y_points_list, function_name x_points_list = [resource[per_key]] y_points_list = [resource[of_key]] function_name = convert.flatten(resource['uid']) else: # Add the data points x_points_list.append(resource[per_key]) y_points_list.append(resource[of_key]) # End of resources, yield the current lists if x_points_list: yield x_points_list, y_points_list, function_name
def resource_sort_key(resource): """Extracts the key from resource used for sorting :param dict resource: profiling resource :return: key used for sorting """ return convert.flatten(resource['uid']), resource['amount']
def resource_group_key(resource): """Extracts the key from resource used for grouping :param dict resource: profiling resource :return: key used for grouping """ return resource['type'], resource.get('subtype', ''), convert.flatten(resource['uid'])
def parse_resources(allocation, workload): """ Parse resources of one allocation :param list allocation: list of raw allocation data :returns structure: formatted structure representing resources of one allocation """ data = {'workload': workload} # parsing amount of allocated memory, # it's the first number on the second line amount = PATTERN_INT.search(allocation[1]).group() data.update({'amount': int(amount)}) # parsing allocate function, # it's the first word on the second line allocator = PATTERN_WORD.search(allocation[1]).group() data.update({'subtype': allocator}) # parsing address of allocated memory, # it's the second number on the second line address = PATTERN_INT.findall(allocation[1])[1] data.update({'address': int(address)}) # parsing stack in the moment of allocation # to getting trace of it trace = parse_stack(allocation[2:]) data.update({'trace': trace}) # parsed data is memory type data.update({'type': 'memory'}) # parsing call trace to get first user call # to allocation function data.update({'uid': parse_allocation_location(trace)}) # update the resource number flattened_uid = convert.flatten(data['uid']) UID_RESOURCE_MAP[flattened_uid] += 1 data.update({'allocation_order': UID_RESOURCE_MAP[flattened_uid]}) return data