Example #1
0
    def test_multiple_process(self):
        data = '{"traceEvents": [{"pid":7762,"tid":7761,"ts":23668655766.343,"dur":5.8,"name":"builtins.exec","caller_lineno":147,"ph":"X","cat":"FEE"}, {"pid":7761,"tid":7761,"ts":23668655766.343,"dur":5.8,"name":"builtins.exec","caller_lineno":147,"ph":"X","cat":"FEE"}], "viztracer_metadata": {"version": "0.6.2"}}'
        snap = ProgSnapshot(data)
        self.assertEqual(len(list(snap.get_trees())), 2)

        # Coverage test
        _ = snap.list_pid()
 def test_change_parent(self):
     data = '{"traceEvents": [{"pid":7762,"tid":7761,"ts":0,"dur":100,"name":"grandpa","caller_lineno":147,"ph":"X","cat":"FEE"}, {"pid":7762,"tid":7761,"ts":50,"dur":10,"name":"grandson","caller_lineno":147,"ph":"X","cat":"FEE"}, {"pid":7762,"tid":7761,"ts":10,"dur":80,"name":"son","caller_lineno":147,"ph":"X","cat":"FEE"}], "viztracer_metadata": {"version": "0.6.2"}}'
     snap = ProgSnapshot(data)
     tree = next(snap.get_trees())
     for node in tree.inorder_traverse():
         if node.parent:
             self.assertIn(node, node.parent.children)
Example #3
0
    def test_invalid(self):
        data = '{"traceEvents": [{"ph": "hello"}], "viztracer_metadata": {"version": "0.6.2"}}'
        with self.assertRaises(ValueError):
            _ = ProgSnapshot(data)

        data = '{"traceEvents": [{"ph": "hello", "pid": 1, "tid": 1}], "viztracer_metadata": {"version": "0.6.2"}}'
        with self.assertRaises(ValueError):
            _ = ProgSnapshot(data)
Example #4
0
 def test_basic(self):
     snap = ProgSnapshot(test1_str)
     tree_len = len(list(snap.get_trees()))
     self.assertEqual(tree_len, 1)
     tree = next(snap.get_trees())
     count = 0
     for _ in tree.inorder_traverse():
         count += 1
     self.assertEqual(count, 12)
Example #5
0
    def test_version(self):
        no_version_str = '{"traceEvents":[]}'
        snap = ProgSnapshot(no_version_str)
        self.assertFalse(snap.valid)

        low_version_str = '{"traceEvents":[], "viztracer_metadata":{"version":"0.0.1"}}'
        snap = ProgSnapshot(low_version_str)
        self.assertFalse(snap.valid)

        # Pure coverage
        high_version_str = '{"traceEvents":[{"pid":7761,"tid":7761,"ts":23668655766.343,"dur":5.8,"name":"builtins.exec","caller_lineno":147,"ph":"X","cat":"FEE"}], "viztracer_metadata":{"version":"1000.0.1"}}'
        snap = ProgSnapshot(high_version_str)
Example #6
0
 def test_next(self):
     snap = ProgSnapshot(test1_str)
     self.assertEqual(snap.curr_frame.node.fullname, "builtins.exec")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "<module>")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "t")
     snap.next()
     self.assertEqual(snap.curr_frame.node.funcname, "t")
     self.assertEqual(snap.curr_frame.curr_children_idx, 1)
Example #7
0
 def test_random_entries(self):
     import random
     snap = ProgSnapshot(test1_str)
     test_obj = json.loads(test1_str)
     random.shuffle(test_obj["traceEvents"])
     snap2 = ProgSnapshot(json.dumps(test_obj))
     self.assertTrue(list(snap.get_trees())[0].is_same(list(snap2.get_trees())[0]))
Example #8
0
 def test_object(self):
     data = '{"traceEvents": [{"pid":1,"tid":1,"ts":0.05,"dur":5.8,"name":"builtins.exec","caller_lineno":147,"ph":"X","cat":"FEE"}, {"ph": "N", "pid": 1, "tid": 1, "ts": 0.1, "id": 1000, "name": "a"}, {"ph": "D", "pid": 1, "tid": 1, "ts": 0.3, "id": 1000, "name": "a"}], "viztracer_metadata": {"version": "0.6.2"}}'
     snap = ProgSnapshot(data)
     self.assertEqual(len(snap.object_events._objects), 1)
Example #9
0
 def test_step(self):
     snap = ProgSnapshot(test1_str)
     self.assertEqual(snap.curr_frame.node.fullname, "builtins.exec")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "<module>")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "t")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "f")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "g")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "h")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "g")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "f")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "h")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "f")
     snap.step()
     self.assertEqual(snap.curr_frame.node.funcname, "t")
Example #10
0
def main(argv=sys.argv):
    parser = argparse.ArgumentParser(
        argv[0],
        formatter_class=argparse.RawDescriptionHelpFormatter,
        usage=usage)
    parser.add_argument(
        '--verbose', '-v', action='count',
        default=0)  # by default quiet, since we write to stdout
    parser.add_argument('--quiet', '-q', action='count', default=0)
    parser.add_argument(
        '--keep-cpython-evals',
        help=
        "keep CPython evaluation stacktraces (instead of replacing) (default: %(default)s)",
        default=False,
        action='store_true')
    parser.add_argument('--no-keep-cpython-evals',
                        dest="keep_cpython_evals",
                        action='store_false')
    parser.add_argument(
        '--allow-mismatch',
        help=
        "Keep going even when we cannot match the C and Python stacktrace (default: %(default)s)",
        default=False,
        action='store_true')
    parser.add_argument('--no-allow-mismatch',
                        dest="allow_mismatch",
                        action='store_false')
    parser.add_argument(
        '--pedantic',
        help=
        "If false, accept known stack mismatch issues (default: %(default)s)",
        default=False,
        action='store_true')
    parser.add_argument('--no-pedantic', dest="pedantic", action='store_false')
    parser.add_argument('--input',
                        '-i',
                        help="VizTracer input (default %(default)s)",
                        default="viztracer.json")
    parser.add_argument('--output',
                        '-o',
                        dest="output",
                        default=None,
                        help="Output filename (default %(default)s)")

    args = parser.parse_args(argv[1:])
    verbose = args.verbose - args.quiet

    perf_script_args = ['--no-inline']
    perf_script_args = ' '.join(perf_script_args)
    cmd = f"perf script {perf_script_args}"
    if verbose >= 2:
        print(f"Running: {cmd}")
    perf_args = shlex.split(cmd)
    perf = subprocess.Popen(perf_args,
                            shell=False,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            text=True)  #, stdin=subprocess.PIPE)

    if args.output is None:
        output = sys.stdout
    else:
        output = open(args.output, "w")

    if verbose >= 1:
        print_stderr("Loading snapshot")
    with open(args.input, "r") as f:
        json_data = f.read()
    snap = ProgSnapshot(json_data)
    # find all pids (or tids)
    pids = list(snap.func_trees)
    for pid in pids.copy():
        pids.extend(list(snap.func_trees[pid]))
    t0 = min(event['ts'] for event in json.loads(json_data)['traceEvents'])

    for header, stacktrace in read_events(perf.stdout):
        print(header, file=output)
        values, _, _ = parse_header(header)
        time = values['time'] - t0
        triggerpid = values['triggerpid']
        if triggerpid in pids:
            try:
                stacktrace = stacktrace_inject(
                    stacktrace,
                    snap,
                    triggerpid,
                    time,
                    keep_cpython_evals=args.keep_cpython_evals,
                    allow_mismatch=args.allow_mismatch,
                    pedantic=args.pedantic)
                for call in stacktrace:
                    print(call, file=output)
            except:
                print(f"Error for event: {header}")
                raise
        print(file=output)
Example #11
0
def main(argv=sys.argv):
    parser = argparse.ArgumentParser(
        argv[0],
        formatter_class=argparse.RawDescriptionHelpFormatter,
        usage=usage)
    parser.add_argument(
        '--verbose', '-v', action='count',
        default=0)  # by default quiet, since we write to stdout
    parser.add_argument('--quiet', '-q', action='count', default=0)
    parser.add_argument('--state',
                        help='State to match (default: %(default)s)',
                        default="S(GIL)")
    parser.add_argument(
        '--strip-take-gil',
        dest="strip_take_gil",
        help=
        "Remove everything from the stack above take_gil (default: %(default)s)",
        default=True,
        action='store_true')
    parser.add_argument('--no-strip-take-gil',
                        dest="strip_take_gil",
                        action='store_false')
    parser.add_argument(
        '--keep-cpython-evals',
        help=
        "keep CPython evaluation stacktraces (instead of replacing) (default: %(default)s)",
        default=False,
        action='store_true')
    parser.add_argument('--no-keep-cpython-evals',
                        dest="keep_cpython_evals",
                        action='store_false')
    parser.add_argument(
        '--allow-mismatch',
        help=
        "Keep going even when we cannot match the C and Python stacktrace (default: %(default)s)",
        default=False,
        action='store_true')
    parser.add_argument('--no-allow-mismatch',
                        dest="allow_mismatch",
                        action='store_false')
    parser.add_argument(
        '--pedantic',
        help=
        "If false, accept known stack mismatch issues (default: %(default)s)",
        default=False,
        action='store_true')
    parser.add_argument('--no-pedantic', dest="pedantic", action='store_false')
    parser.add_argument('--input-perf',
                        help="Perf input (default %(default)s)",
                        default="perf-sched.data")
    parser.add_argument('--input-viztracer',
                        help="VizTracer input (default %(default)s)",
                        default="viztracer.json")
    parser.add_argument('--output',
                        '-o',
                        dest="output",
                        default=None,
                        help="Output filename (default %(default)s)")

    args = parser.parse_args(argv[1:])
    verbose = args.verbose - args.quiet

    perf_script_args = ['--no-inline']
    perf_script_args = ' '.join(perf_script_args)
    cmd = f"perf script {perf_script_args} -i {args.input_perf}"
    if verbose >= 2:
        print(f"Running: {cmd}")
    perf_args = shlex.split(cmd)
    perf = subprocess.Popen(perf_args,
                            shell=False,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            text=True)  #, stdin=subprocess.PIPE)

    if args.output is None:
        output = sys.stdout
    else:
        output = open(args.output, "w")

    if verbose >= 1:
        print_stderr("Loading snapshot")
    with open(args.input_viztracer, "r") as f:
        json_data = f.read()
    snap = ProgSnapshot(json_data)
    # find all pids (or tids)
    pids = list(snap.func_trees)
    for pid in pids.copy():
        pids.extend(list(snap.func_trees[pid]))
    t0 = min(event['ts'] for event in json.loads(json_data)['traceEvents']
             if 'ts' in event)

    for header, stacktrace, event in perf2trace(perf.stdout, verbose):
        if event['name'] == args.state:
            values, _, _ = parse_header(header)
            time = values['time'] - t0
            triggerpid = event['tid']
            if triggerpid in pids:
                try:
                    stacktrace = stacktrace_inject(
                        stacktrace,
                        snap,
                        triggerpid,
                        time,
                        keep_cpython_evals=args.keep_cpython_evals,
                        allow_mismatch=args.allow_mismatch,
                        pedantic=args.pedantic)
                    if args.strip_take_gil:
                        take_gil_index = None
                        for i, call in enumerate(stacktrace):
                            if 'take_gil' in call:
                                take_gil_index = i
                        if take_gil_index is not None:  # shouldn't it be always there?
                            stacktrace = stacktrace[take_gil_index:]
                    for call in stacktrace:
                        ptr, signature = call.split(' ', 1)
                        print(signature, file=output)
                except:
                    print_stderr(f"Error for event: {header}")
                    raise
            print(int(event['dur']))
            print(file=output)
Example #12
0
 def test_invalid_filename(self):
     data = '{"traceEvents": [{"pid":7761,"tid":7761,"ts":23668655769.443,"dur":0.4,"name":"_handle_fromlist (<frozen importlib._bootstrap>:1017)","caller_lineno":10,"ph":"X","cat":"FEE"}], "viztracer_metadata": {"version": "0.9.5"}}'  # noqa: E501
     prog = ProgSnapshot(data)
     prog.show()