Beispiel #1
0
def is_perf_file(f):
    for line in f:
        if (line[0] == '#'):
            continue
        r = event_regexp.search(line)
        if r:
            return True
        return False
Beispiel #2
0
def _is_perf_file(file_path):
    f = get_file(file_path)
    for line in f:
        if (line[0] == '#'):
            continue
        r = event_regexp.search(line)
        if r:
            f.close()
            return True
        f.close()
        return False
Beispiel #3
0
def calculate_profile_range(filename):
    start = float("+inf")
    end = float("-inf")
    index_factor = 100  # save one timestamp per this many lines

    file_path = join(config.PROFILE_DIR, filename)

    # check for cached times
    mtime = getmtime(file_path)
    if file_path in stack_times:
        if mtime == stack_mtimes[file_path]:
            return stack_times[file_path]

    f = get_file(file_path)

    linenum = -1
    stack_index[file_path] = []
    for line in f:
        linenum += 1
        # 1. Skip '#' comments
        # 2. Since we're only interested in the event summary lines, skip the
        # stack trace lines based on those that start with '\t'. This is a
        # performance optimization that avoids using the regexp needlessly,
        # and makes a large difference.
        if (line[0] == '#' or line[0] == '\t'):
            continue
        r = event_regexp.search(line)
        if (r):
            ts = float(r.group(1))
            if ((linenum % index_factor) == 0):
                stack_index[file_path].append([linenum, ts])
            if (ts < start):
                start = ts
            elif (ts > end):
                end = ts

    f.close()
    times = collections.namedtuple('range', ['start', 'end'])(floor(start),
                                                              ceil(end))
    stack_times[file_path] = times
    stack_mtimes[file_path] = mtime

    return times
Beispiel #4
0
def perf_generate_flame_graph(filename, range_start=None, range_end=None):
    file_path = join(config.PROFILE_DIR, filename)

    (f, mime) = get_file(file_path)

    # calculate profile file range
    r = calculate_profile_range(filename)
    start = r.start
    end = r.end

    # check range. default to full range if not specified.
    if (range_end):
        if ((start + range_end) > end):
            print("ERROR: Bad range, %s -> %s." % (str(start), str(end)))
            return abort(416)
        else:
            end = start + range_end
    if (range_start):
        start = start + range_start

    if (start > end):
        print("ERROR: Bad range, %s -> %s." % (str(start), str(end)))
        return abort(416)

    root = {}
    root['c'] = []
    root['n'] = "root"
    root['l'] = ""
    root['v'] = 0

    stack = []
    ts = -1
    comm = ""
    # overscan is seconds beyond the time range to keep scanning, which allows
    # for some out-of-order samples up to this duration
    overscan = 0.1

    # determine skip lines
    lastline = 0
    skiplines = 0
    if file_path in stack_index:
        for pair in stack_index[file_path]:
            if start < pair[1]:
                # scanned too far, use last entry
                skiplines = lastline
                break
            lastline = pair[0]

    # process perf script output and search for two things:
    # - event_regexp: to identify event timestamps
    # - idle_regexp: for filtering idle stacks
    linenum = -1
    for line in f:
        linenum += 1
        # Performance optimization. Makes a large difference.
        if (linenum < skiplines):
            continue
        # skip comments
        if (line[0] == '#'):
            continue

        # As a performance optimization, skip an event regexp search if the
        # line looks like a stack trace based on starting with '\t'. This
        # makes a big difference.
        r = None
        if (line[0] != '\t'):
            r = event_regexp.search(line)
        if (r):
            if (stack):
                # process prior stack
                stackstr = ""
                for pair in stack:
                    stackstr += pair[0] + ";"
                if (idle_regexp.search(stackstr)):
                    # skip idle
                    stack = []
                elif (ts >= start and ts <= end):
                    root = add_stack(root, stack, comm)
                stack = []
            ts = float(r.group(1))
            if (ts > end + overscan):
                break
            r = comm_regexp.search(line)
            if (r):
                comm = r.group(1).rstrip()
                stack.append([comm, ""])
            else:
                stack.append(["<unknown>", ""])
        else:
            r = frame_regexp.search(line)
            if (r):
                name = r.group(1)
                # strip instruction offset (+0xfe200...)
                c = name.find("+")
                if (c > 0):
                    name = name[:c]
                stack.insert(1, [name, r.group(2)])
    # last stack
    if (ts >= start and ts <= end):
        root = add_stack(root, stack, comm)

    # close file
    f.close()

    return root