1"""Benchmark the turnaround time starting a debugger and run to the breakpoint with lldb vs. gdb."""
2
3from __future__ import print_function
4
5
6import sys
7import lldb
8from lldbsuite.test.lldbbench import *
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import configuration
12from lldbsuite.test import lldbutil
13
14
15class CompileRunToBreakpointBench(BenchBase):
16
17    def setUp(self):
18        BenchBase.setUp(self)
19        self.exe = lldbtest_config.lldbExec
20        self.function = 'Driver::MainLoop()'
21        self.count = 3
22
23        self.lldb_avg = None
24        self.gdb_avg = None
25
26    @benchmarks_test
27    @no_debug_info_test
28    @expectedFailureAll(
29        oslist=["windows"],
30        bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
31    def test_run_lldb_then_gdb(self):
32        """Benchmark turnaround time with lldb vs. gdb."""
33        print()
34        self.run_lldb_turnaround(self.exe, self.function, self.count)
35        print("lldb turnaround benchmark:", self.stopwatch)
36        self.run_gdb_turnaround(self.exe, self.function, self.count)
37        print("gdb turnaround benchmark:", self.stopwatch)
38        print("lldb_avg/gdb_avg: %f" % (self.lldb_avg / self.gdb_avg))
39
40    def run_lldb_turnaround(self, exe, function, count):
41        import pexpect
42
43        def run_one_round():
44            prompt = self.child_prompt
45
46            # So that the child gets torn down after the test.
47            self.child = pexpect.spawn(
48                '%s %s %s' %
49                (lldbtest_config.lldbExec, self.lldbOption, exe))
50            child = self.child
51
52            # Turn on logging for what the child sends back.
53            if self.TraceOn():
54                child.logfile_read = sys.stdout
55
56            child.expect_exact(prompt)
57            child.sendline('breakpoint set -F %s' % function)
58            child.expect_exact(prompt)
59            child.sendline('run')
60            child.expect_exact(prompt)
61
62        # Set self.child_prompt, which is "(lldb) ".
63        self.child_prompt = '(lldb) '
64        # Reset the stopwatch now.
65        self.stopwatch.reset()
66
67        for i in range(count + 1):
68            # Ignore the first invoke lldb and run to the breakpoint turnaround
69            # time.
70            if i == 0:
71                run_one_round()
72            else:
73                with self.stopwatch:
74                    run_one_round()
75
76            self.child.sendline('quit')
77            try:
78                self.child.expect(pexpect.EOF)
79            except:
80                pass
81
82        self.lldb_avg = self.stopwatch.avg()
83        self.child = None
84
85    def run_gdb_turnaround(self, exe, function, count):
86        import pexpect
87
88        def run_one_round():
89            prompt = self.child_prompt
90
91            # So that the child gets torn down after the test.
92            self.child = pexpect.spawn('gdb --nx %s' % exe)
93            child = self.child
94
95            # Turn on logging for what the child sends back.
96            if self.TraceOn():
97                child.logfile_read = sys.stdout
98
99            child.expect_exact(prompt)
100            child.sendline('break %s' % function)
101            child.expect_exact(prompt)
102            child.sendline('run')
103            child.expect_exact(prompt)
104
105        # Set self.child_prompt, which is "(gdb) ".
106        self.child_prompt = '(gdb) '
107        # Reset the stopwatch now.
108        self.stopwatch.reset()
109
110        for i in range(count + 1):
111            # Ignore the first invoke lldb and run to the breakpoint turnaround
112            # time.
113            if i == 0:
114                run_one_round()
115            else:
116                with self.stopwatch:
117                    run_one_round()
118
119            self.child.sendline('quit')
120            self.child.expect_exact('The program is running.  Exit anyway?')
121            self.child.sendline('y')
122            try:
123                self.child.expect(pexpect.EOF)
124            except:
125                pass
126
127        self.gdb_avg = self.stopwatch.avg()
128        self.child = None
129