blob: 7dd0ad0782f6e51c429b0b1ee9b98fb0fb5383ed [file] [log] [blame]
Greg Clayton52e63782013-03-23 01:44:48 +00001#!/usr/bin/python
2
3#----------------------------------------------------------------------
4# Be sure to add the python path that points to the LLDB shared library.
5# On MacOSX csh, tcsh:
6# setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
7# On MacOSX sh, bash:
8# export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
9#----------------------------------------------------------------------
10
11import commands
12import optparse
13import os
14import platform
Greg Clayton2d95f352013-03-26 21:00:29 +000015import re
Greg Clayton52e63782013-03-23 01:44:48 +000016import resource
17import sys
18import time
19
20#----------------------------------------------------------------------
21# Code that auto imports LLDB
22#----------------------------------------------------------------------
23try:
24 # Just try for LLDB in case PYTHONPATH is already correctly setup
25 import lldb
26except ImportError:
27 lldb_python_dirs = list()
28 # lldb is not in the PYTHONPATH, try some defaults for the current platform
29 platform_system = platform.system()
30 if platform_system == 'Darwin':
31 # On Darwin, try the currently selected Xcode directory
32 xcode_dir = commands.getoutput("xcode-select --print-path")
33 if xcode_dir:
34 lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
35 lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
36 lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
37 success = False
38 for lldb_python_dir in lldb_python_dirs:
39 if os.path.exists(lldb_python_dir):
40 if not (sys.path.__contains__(lldb_python_dir)):
41 sys.path.append(lldb_python_dir)
42 try:
43 import lldb
44 except ImportError:
45 pass
46 else:
47 print 'imported lldb from: "%s"' % (lldb_python_dir)
48 success = True
49 break
50 if not success:
51 print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
52 sys.exit(1)
53
54
55class Timer:
56 def __enter__(self):
57 self.start = time.clock()
58 return self
59
60 def __exit__(self, *args):
61 self.end = time.clock()
62 self.interval = self.end - self.start
63
64class TestCase:
65 """Class that aids in running performance tests."""
66 def __init__(self):
67 self.verbose = False
68 self.debugger = lldb.SBDebugger.Create()
69 self.target = None
70 self.process = None
71 self.thread = None
72 self.launch_info = None
73 self.listener = self.debugger.GetListener()
74
75 def Setup(self, args):
76 self.launch_info = lldb.SBLaunchInfo(args)
77
78 def Run (self, args):
79 assert False, "performance.TestCase.Run() must be subclassed"
80
81 def Launch(self):
82 if self.target:
83 error = lldb.SBError()
84 self.process = self.target.Launch (self.launch_info, error);
85 if not error.Success():
86 print "error: %s" % error.GetCString()
87 if self.process:
88 self.process.GetBroadcaster().AddListener(self.listener, lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitInterrupt);
89 return True
90 return False
91
92 def WaitForNextProcessEvent (self):
93 event = None
94 if self.process:
95 while event is None:
96 process_event = lldb.SBEvent()
97 if self.listener.WaitForEvent (lldb.UINT32_MAX, process_event):
98 state = lldb.SBProcess.GetStateFromEvent (process_event)
99 if self.verbose:
100 print "event = %s" % (lldb.SBDebugger.StateAsCString(state))
101 if lldb.SBProcess.GetRestartedFromEvent(process_event):
102 continue
103 if state == lldb.eStateInvalid or state == lldb.eStateDetached or state == lldb.eStateCrashed or state == lldb.eStateUnloaded or state == lldb.eStateExited:
104 event = process_event
105 elif state == lldb.eStateConnected or state == lldb.eStateAttaching or state == lldb.eStateLaunching or state == lldb.eStateRunning or state == lldb.eStateStepping or state == lldb.eStateSuspended:
106 continue
107 elif state == lldb.eStateStopped:
108 event = process_event
109 call_test_step = True
110 fatal = False
111 selected_thread = False
112 for thread in self.process:
113 frame = thread.GetFrameAtIndex(0)
114 select_thread = False
115 stop_reason = thread.GetStopReason();
116 if self.verbose:
117 print "tid = %#x pc = %#x " % (thread.GetThreadID(),frame.GetPC()),
118 if stop_reason == lldb.eStopReasonNone:
119 if self.verbose:
120 print "none"
121 elif stop_reason == lldb.eStopReasonTrace:
122 select_thread = True
123 if self.verbose:
124 print "trace"
125 elif stop_reason == lldb.eStopReasonPlanComplete:
126 select_thread = True
127 if self.verbose:
128 print "plan complete"
129 elif stop_reason == lldb.eStopReasonThreadExiting:
130 if self.verbose:
131 print "thread exiting"
132 elif stop_reason == lldb.eStopReasonExec:
133 if self.verbose:
134 print "exec"
135 elif stop_reason == lldb.eStopReasonInvalid:
136 if self.verbose:
137 print "invalid"
138 elif stop_reason == lldb.eStopReasonException:
139 select_thread = True
140 if self.verbose:
141 print "exception"
142 fatal = True
143 elif stop_reason == lldb.eStopReasonBreakpoint:
144 select_thread = True
145 if self.verbose:
146 print "breakpoint id = %d.%d" % (thread.GetStopReasonDataAtIndex(0),thread.GetStopReasonDataAtIndex(1))
147 elif stop_reason == lldb.eStopReasonWatchpoint:
148 select_thread = True
149 if self.verbose:
150 print "watchpoint id = %d" % (thread.GetStopReasonDataAtIndex(0))
151 elif stop_reason == lldb.eStopReasonSignal:
152 select_thread = True
153 if self.verbose:
154 print "signal %d" % (thread.GetStopReasonDataAtIndex(0))
155
156 if select_thread and not selected_thread:
157 self.thread = thread;
158 selected_thread = self.process.SetSelectedThread(thread);
159 if fatal:
160 # if self.verbose:
161 # Xcode.RunCommand(self.debugger,"bt all",true);
162 sys.exit(1);
163 return event
164
Greg Clayton2d95f352013-03-26 21:00:29 +0000165class Measurement:
166 '''A class that encapsulates a measurement'''
167 def Measure(self):
168 assert False, "performance.Measurement.Measure() must be subclassed"
169
170class MemoryMeasurement(Measurement):
171 '''A class that can measure memory statistics for a process.'''
172 def __init__(self, pid):
173 self.pid = pid
174 self.stats = ["rprvt","rshrd","rsize","vsize","vprvt","kprvt","kshrd","faults","cow","pageins"]
175 self.command = "top -l 1 -pid %u -stats %s" % (self.pid, ",".join(self.stats))
176 self.value = dict()
177
178 def Measure(self):
179 output = commands.getoutput(self.command).split("\n")[-1]
180 values = re.split('[-+\s]+', output)
181 for (idx, stat) in enumerate(values):
182 multiplier = 1
183 if stat:
184 if stat[-1] == 'K':
185 multiplier = 1024;
186 stat = stat[:-1]
187 elif stat[-1] == 'M':
188 multiplier = 1024*1024;
189 stat = stat[:-1]
190 elif stat[-1] == 'G':
191 multiplier = 1024*1024*1024;
192 elif stat[-1] == 'T':
193 multiplier = 1024*1024*1024*1024;
194 stat = stat[:-1]
195 self.value[self.stats[idx]] = int (stat) * multiplier
196
197 def __str__(self):
198 '''Dump the MemoryMeasurement current value'''
199 s = ''
200 for key in self.value.keys():
201 if s:
202 s += "\n"
203 s += "%8s = %s" % (key, self.value[key])
204 return s
205
Greg Clayton52e63782013-03-23 01:44:48 +0000206
207class TesterTestCase(TestCase):
208
209 def Run (self, args):
210 self.Setup(args)
211 self.verbose = True
Greg Clayton2d95f352013-03-26 21:00:29 +0000212 #self.breakpoints = { 'name' : { 'main' } : , 'malloc' {}
213 with Timer() as total_time:
214 self.target = self.debugger.CreateTarget(args[0])
215 if self.target:
Greg Clayton52e63782013-03-23 01:44:48 +0000216 with Timer() as breakpoint_timer:
217 self.target.BreakpointCreateByName("main")
Greg Clayton2d95f352013-03-26 21:00:29 +0000218 print('Breakpoint time = %.03f sec.' % breakpoint_timer.interval)
219 if self.Launch():
220 self.WaitForNextProcessEvent();
221 self.process.Kill()
222 else:
223 print "error: failed to launch process"
Greg Clayton52e63782013-03-23 01:44:48 +0000224 else:
Greg Clayton2d95f352013-03-26 21:00:29 +0000225 print "error: failed to create target with '%s'" % (args[0])
226 print('Total time = %.03f sec.' % total_time.interval)
227
Greg Clayton52e63782013-03-23 01:44:48 +0000228
229if __name__ == '__main__':
230 lldb.SBDebugger.Initialize()
231 test = TesterTestCase()
232 test.Run (sys.argv[1:])
Greg Clayton2d95f352013-03-26 21:00:29 +0000233 mem = MemoryMeasurement(os.getpid())
234 mem.Measure()
235 print str(mem)
Greg Clayton52e63782013-03-23 01:44:48 +0000236 lldb.SBDebugger.Terminate()
Greg Clayton2d95f352013-03-26 21:00:29 +0000237 # print "sleeeping for 100 seconds"
238 # time.sleep(100)