Esempio n. 1
0
def trace_event_read_offsets(file_path, mtime):
    try:
        f = get_file(file_path)
        profile = json.load(f)
    except JSONDecodeError:
        abort(500, 'Failed to parse profile.')
    finally:
        f.close()

    root_slices = []
    events = {}
    offsets = []

    (start_time, end_time) = get_time_range(file_path, mtime, profile)

    # process all events in the profile to extract root events
    for row in profile:
        key = str(row['pid']) + '_' + str(row['tid'])
        if row['ph'] == 'B' or row['ph'] == 'E':
            if row['ph'] == 'B':
                if key not in events:
                    events[key] = {'ts': row['ts'], 'tts': row['tts'], 'children_count': 0}
                else:
                    events[key]['children_count'] = events[key]['children_count'] + 1
            elif row['ph'] == 'E':
                if events[key]['children_count'] > 0:
                    events[key]['children_count'] = events[key]['children_count'] - 1
                else:
                    root_slices.append({'start': events[key]['ts'], 'cpu_start': events[key]['tts'], 'end': row['ts'], 'cpu_end': row['tts']})
                    del events[key]
        elif row['ph'] == 'X':
            if 'dur' in row and row['dur'] > 0 and 'tdur' in row and row['tdur'] > 0:
                if key not in events:  # it's a root event
                    root_slices.append({'start': row['ts'], 'cpu_start': row['tts'], 'end': row['ts'] + row['dur'], 'cpu_end': row['tts'] + row['tdur']})

    # process each root event and generate time offsets based on frequency
    for s in root_slices:
        first_index = math.floor(s['start'] / u_sec_interval) * u_sec_interval
        last_index = math.ceil(s['end'] / u_sec_interval) * u_sec_interval
        # TODO: user cpu usage
        # usage = (s['cpu_end'] - s['cpu_start']) / (s['end'] - s['start'])
        for i in range(first_index, last_index, u_sec_interval):
            offsets.append(i / 1000000)
    res = collections.namedtuple('offsets', ['start', 'end', 'offsets'])(start_time / 1000000, end_time / 1000000, offsets)
    return res
Esempio n. 2
0
def trace_event_generate_flame_graph(file_path, mtime, range_start, range_end):
    try:
        f = get_file(file_path)
        profile = json.load(f)
    except JSONDecodeError:
        abort(500, 'Failed to parse profile.')
    finally:
        f.close()

    root = {'name': 'root', 'value': 0, 'children': []}
    open_partial_slices = {}

    (start_time, end_time) = get_time_range(file_path, mtime, profile)

    adjusted_start = (math.floor(start_time / 1000000) + range_start) * 1000000
    adjusted_end = (math.floor(start_time / 1000000) + range_end) * 1000000

    def filter_and_adjust_slice_times(profile_slice):
        # slice starts after the range
        # slice ends before the range
        if profile_slice['ts'] > adjusted_end or (
                profile_slice['ts'] + profile_slice['dur']) < adjusted_start:
            return None
        # slice starts before the range, need to adjust start time and duration
        if profile_slice['ts'] < adjusted_start:
            ts_diff = profile_slice['ts'] - adjusted_start
            profile_slice['ts']: adjusted_start
            profile_slice['dur'] = profile_slice['dur'] + ts_diff
        # slice ends after the range, need to adjust duration
        if (profile_slice['ts'] + profile_slice['dur']) > adjusted_end:
            ts_diff = adjusted_end - (profile_slice['ts'] +
                                      profile_slice['dur'])
            profile_slice['dur'] = profile_slice['dur'] + ts_diff
        # filter children
        if len(profile_slice['children']) > 0:
            filtered_children = []
            for child in profile_slice['children']:
                filtered_child = filter_and_adjust_slice_times(child)
                if filtered_child is not None:
                    filtered_children.append(filtered_child)
            profile_slice['children'] = filtered_children
        return profile_slice

    def get_child_slice(parent_slice, name):
        for index, child in enumerate(parent_slice['children']):
            if child['name'] == name:
                return parent_slice['children'].pop(index)
        return None

    def insert_slice(parent_slice, new_slice):
        child_slice = get_child_slice(parent_slice, new_slice['name'])
        if child_slice is None:
            child_slice = {
                'name': new_slice['name'],
                'value': 0,
                'children': []
            }
        for child in new_slice['children']:
            insert_slice(child_slice, child)
        child_slice['value'] += new_slice['value']
        parent_slice['children'].append(child_slice)

    def check_thread(pid, tid):
        if pid not in open_partial_slices:
            open_partial_slices[pid] = {}
        if tid not in open_partial_slices[pid]:
            open_partial_slices[pid][tid] = []

    def begin_slice(pid, tid, cat, name, ts, tts):
        check_thread(pid, tid)
        open_partial_slices[pid][tid].append({
            'pid': pid,
            'tid': tid,
            'cat': cat,
            'name': name,
            'ts': ts,
            'tts': tts,
            'children': []
        })

    def end_slice(pid, tid, ts, tts):
        partial_slice_count = len(open_partial_slices[pid][tid])
        if partial_slice_count > 0:
            current_slice = open_partial_slices[pid][tid].pop()
            current_slice['dur'] = ts - current_slice['ts']
            current_slice['tdur'] = tts - current_slice['tts']
            if current_slice['dur'] > 0:
                current_slice[
                    'value'] = current_slice['tdur'] / current_slice['dur']
            partial_slice_count = len(open_partial_slices[pid][tid])
            if partial_slice_count > 0:
                open_partial_slices[pid][tid][
                    partial_slice_count - 1]['children'].append(current_slice)
            else:
                filtered_slice = filter_and_adjust_slice_times(current_slice)
                if filtered_slice is not None:
                    insert_slice(root, current_slice)
        else:
            raise Exception("end_slice called without an open slice")

    for row in profile:
        if row['ph'] == 'B' or row['ph'] == 'E':
            if row['ph'] == 'B':
                begin_slice(row['pid'], row['tid'], row['cat'], row['name'],
                            row['ts'], row['tts'])
            elif row['ph'] == 'E':
                end_slice(row['pid'], row['tid'], row['ts'], row['tts'])
        elif row['ph'] == 'X':
            if 'dur' in row and row['dur'] > 0 and 'tdur' in row and row[
                    'tdur'] > 0:
                begin_slice(row['pid'], row['tid'], row['cat'], row['name'],
                            row['ts'], row['tts'])
                end_slice(row['pid'], row['tid'], row['ts'] + row['dur'],
                          row['tts'] + row['tdur'])

    return root