blob: c8578367b5b030ff2d6ee45cd4374ff86d8967bb [file] [log] [blame]
Greg Clayton5dbe5d42013-03-21 03:39:51 +00001//===-- sketch.cpp ----------------------------------------------*- C++ -*-===//
Enrico Granataf58cece2013-03-08 20:29:13 +00002//
Greg Clayton5dbe5d42013-03-21 03:39:51 +00003// The LLVM Compiler Infrastructure
Enrico Granataf58cece2013-03-08 20:29:13 +00004//
Greg Clayton5dbe5d42013-03-21 03:39:51 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Enrico Granataf58cece2013-03-08 20:29:13 +00007//
Greg Clayton5dbe5d42013-03-21 03:39:51 +00008//===----------------------------------------------------------------------===//
Enrico Granataf58cece2013-03-08 20:29:13 +00009
10#include <CoreFoundation/CoreFoundation.h>
11
12#include "lldb-perf/lib/Timer.h"
13#include "lldb-perf/lib/Metric.h"
14#include "lldb-perf/lib/Measurement.h"
15#include "lldb-perf/lib/TestCase.h"
16#include "lldb-perf/lib/Xcode.h"
17
18#include <iostream>
19#include <unistd.h>
20#include <fstream>
Enrico Granata4b4e24d2013-04-01 17:42:02 +000021#include <getopt.h>
Enrico Granataf58cece2013-03-08 20:29:13 +000022
Greg Clayton7b8f7382013-03-18 22:34:00 +000023using namespace lldb_perf;
Enrico Granataf58cece2013-03-08 20:29:13 +000024
Enrico Granata85e9d6d2013-04-12 21:31:02 +000025static struct option g_long_options[] = {
26 { "verbose", no_argument, NULL, 'v' },
27 { "sketch", required_argument, NULL, 'c' },
28 { "foobar", required_argument, NULL, 'f' },
29 { "out-file", required_argument, NULL, 'o' },
30 { NULL, 0, NULL, 0 }
31};
32
Enrico Granataf58cece2013-03-08 20:29:13 +000033class SketchTest : public TestCase
34{
35public:
36 SketchTest () :
Greg Clayton1080faf2013-03-19 19:30:33 +000037 m_fetch_frames_measurement ([this] () -> void
38 {
39 Xcode::FetchFrames (GetProcess(),false,false);
40 }, "fetch-frames", "time to dump backtrace for every frame in every thread"),
41 m_file_line_bp_measurement([this] (const char* file, uint32_t line) -> void
42 {
43 Xcode::CreateFileLineBreakpoint(GetTarget(), file, line);
44 }, "file-line-bkpt", "time to set a breakpoint given a file and line"),
45 m_fetch_modules_measurement ([this] () -> void
46 {
47 Xcode::FetchModules(GetTarget());
48 }, "fetch-modules", "time to get info for all modules in the process"),
49 m_fetch_vars_measurement([this] (int depth) -> void
50 {
51 SBProcess process (GetProcess());
52 auto threads_count = process.GetNumThreads();
53 for (size_t thread_num = 0; thread_num < threads_count; thread_num++)
54 {
55 SBThread thread(process.GetThreadAtIndex(thread_num));
56 SBFrame frame(thread.GetFrameAtIndex(0));
57 Xcode::FetchVariables(frame,depth,GetVerbose());
58 }
59 }, "fetch-vars", "time to dump variables for the topmost frame in every thread"),
60 m_run_expr_measurement([this] (SBFrame frame, const char* expr) -> void
61 {
62 SBValue value(frame.EvaluateExpression(expr, lldb::eDynamicCanRunTarget));
63 Xcode::FetchVariable (value, 0, GetVerbose());
64 }, "run-expr", "time to evaluate an expression and display the result")
Enrico Granata85e9d6d2013-04-12 21:31:02 +000065 {
66 m_app_path.clear();
67 m_out_path.clear();
68 m_doc_path.clear();
69 m_print_help = false;
70 }
Enrico Granataf58cece2013-03-08 20:29:13 +000071
72 virtual
73 ~SketchTest ()
74 {
75 }
76
Greg Claytone0b924e2013-03-19 04:41:22 +000077 virtual bool
Enrico Granata85e9d6d2013-04-12 21:31:02 +000078 ParseOption (int short_option, const char* optarg)
79 {
80 switch (short_option)
81 {
82 case 0:
83 return false;
84
85 case -1:
86 return false;
87
88 case '?':
89 case 'h':
90 m_print_help = true;
91 break;
92
93 case 'v':
94 SetVerbose(true);
95 break;
96
97 case 'c':
98 {
99 SBFileSpec file(optarg);
100 if (file.Exists())
101 SetExecutablePath(optarg);
102 else
103 fprintf(stderr, "error: file specified in --sketch (-c) option doesn't exist: '%s'\n", optarg);
104 }
105 break;
106
107 case 'f':
108 {
109 SBFileSpec file(optarg);
110 if (file.Exists())
111 SetDocumentPath(optarg);
112 else
113 fprintf(stderr, "error: file specified in --foobar (-f) option doesn't exist: '%s'\n", optarg);
114 }
115 break;
116
117 case 'o':
118 SetResultFilePath(optarg);
119 break;
120
121 default:
122 m_print_help = true;
123 fprintf (stderr, "error: unrecognized option %c\n", short_option);
124 break;
125 }
126 return true;
127 }
128
129 virtual struct option*
130 GetLongOptions ()
131 {
132 return g_long_options;
133 }
134
135 virtual bool
Enrico Granata8fab9fd2013-04-01 18:02:25 +0000136 Setup (int& argc, const char**& argv)
Enrico Granataf58cece2013-03-08 20:29:13 +0000137 {
Enrico Granataf58cece2013-03-08 20:29:13 +0000138 TestCase::Setup(argc,argv);
Enrico Granata85e9d6d2013-04-12 21:31:02 +0000139 bool error = false;
140
141 if (GetExecutablePath() == NULL)
142 {
143 // --sketch is mandatory
144 error = true;
145 fprintf (stderr, "error: the '--sketch=PATH' option is mandatory\n");
146 }
147
148 if (GetDocumentPath() == NULL)
149 {
150 // --foobar is mandatory
151 error = true;
152 fprintf (stderr, "error: the '--foobar=PATH' option is mandatory\n");
153 }
154
155 if (error || GetPrintHelp())
156 {
157 puts(R"(
158 NAME
159 lldb_perf_sketch -- a tool that measures LLDB peformance while debugging sketch.
160
161 SYNOPSIS
162 lldb_perf_sketch --sketch=PATH --foobar=PATH [--out-file=PATH --verbose]
163
164 DESCRIPTION
165 Runs a set of static timing and memory tasks against sketch and outputs results
166 to a plist file.
167 )");
168 }
169
170 if (error)
171 {
172 exit(1);
173 }
Enrico Granataa571e212013-04-15 19:07:38 +0000174 lldb::SBLaunchInfo launch_info = GetLaunchInfo();
Enrico Granataf58cece2013-03-08 20:29:13 +0000175 m_target = m_debugger.CreateTarget(m_app_path.c_str());
Greg Clayton1080faf2013-03-19 19:30:33 +0000176 m_file_line_bp_measurement("SKTDocument.m",245);
177 m_file_line_bp_measurement("SKTDocument.m",283);
178 m_file_line_bp_measurement("SKTText.m",326);
Greg Claytone0b924e2013-03-19 04:41:22 +0000179 return Launch (launch_info);
Enrico Granataf58cece2013-03-08 20:29:13 +0000180 }
181
Enrico Granataa571e212013-04-15 19:07:38 +0000182 lldb::SBLaunchInfo
183 GetLaunchInfo ()
184 {
185 const char* file_arg = m_doc_path.c_str();
186 const char* persist_arg = "-ApplePersistenceIgnoreState";
187 const char* persist_skip = "YES";
188 const char* empty = nullptr;
189 const char* args[] = {file_arg,persist_arg,persist_skip,empty};
190 return SBLaunchInfo(args);
191 }
192
Enrico Granataf58cece2013-03-08 20:29:13 +0000193 void
194 DoTest ()
195 {
Greg Clayton1080faf2013-03-19 19:30:33 +0000196 m_fetch_frames_measurement();
197 m_fetch_modules_measurement();
198 m_fetch_vars_measurement(1);
Enrico Granataf58cece2013-03-08 20:29:13 +0000199 }
200
Greg Clayton7b8f7382013-03-18 22:34:00 +0000201 virtual void
202 TestStep (int counter, ActionWanted &next_action)
Enrico Granataf58cece2013-03-08 20:29:13 +0000203 {
Greg Clayton7b8f7382013-03-18 22:34:00 +0000204 switch (counter)
205 {
206 case 0:
Enrico Granataa571e212013-04-15 19:07:38 +0000207 case 10:
Greg Clayton7b8f7382013-03-18 22:34:00 +0000208 {
209 DoTest ();
Enrico Granataa571e212013-04-15 19:07:38 +0000210 if (counter == 0)
211 m_file_line_bp_measurement("SKTDocument.m",254);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000212 next_action.Continue();
213 }
214 break;
215
216 case 1:
Enrico Granataa571e212013-04-15 19:07:38 +0000217 case 11:
Greg Clayton7b8f7382013-03-18 22:34:00 +0000218 {
219 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000220 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"properties");
221 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[properties description]");
222 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"typeName");
223 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"data");
224 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[data description]");
Greg Clayton7b8f7382013-03-18 22:34:00 +0000225 next_action.Continue();
226 }
227 break;
228
229 case 2:
Enrico Granataa571e212013-04-15 19:07:38 +0000230 case 12:
Greg Clayton7b8f7382013-03-18 22:34:00 +0000231 {
232 DoTest ();
233 next_action.Continue();
234 }
235 break;
236
237 case 3:
Enrico Granataa571e212013-04-15 19:07:38 +0000238 case 13:
Greg Clayton7b8f7382013-03-18 22:34:00 +0000239 {
240 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000241 next_action.StepOver(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000242 }
243 break;
244
245 case 4:
Enrico Granataa571e212013-04-15 19:07:38 +0000246 case 14:
247
Greg Clayton7b8f7382013-03-18 22:34:00 +0000248 {
249 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000250 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"layoutManager");
251 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"contents");
252 next_action.StepOver(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000253 }
254 break;
255
256 case 5:
Enrico Granataa571e212013-04-15 19:07:38 +0000257 case 15:
Greg Clayton7b8f7382013-03-18 22:34:00 +0000258 {
259 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000260 next_action.StepOver(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000261 }
262 break;
263
264 case 6:
Enrico Granataa571e212013-04-15 19:07:38 +0000265 case 16:
Greg Clayton7b8f7382013-03-18 22:34:00 +0000266 {
267 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000268 next_action.StepOver(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000269 }
270 break;
271
272 case 7:
Enrico Granataa571e212013-04-15 19:07:38 +0000273 case 17:
Greg Clayton7b8f7382013-03-18 22:34:00 +0000274 {
275 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000276 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"@\"an NSString\"");
277 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[(id)@\"an NSString\" description]");
278 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"@[@1,@2,@3]");
279 next_action.StepOut(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000280 }
281 break;
282
283 case 8:
Enrico Granataa571e212013-04-15 19:07:38 +0000284 case 18:
Greg Clayton7b8f7382013-03-18 22:34:00 +0000285 {
286 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000287 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[graphics description]");
288 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[selectionIndexes description]");
289 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"(BOOL)NSIntersectsRect(rect, graphicDrawingBounds)");
Greg Clayton7b8f7382013-03-18 22:34:00 +0000290 }
291 break;
Enrico Granataa571e212013-04-15 19:07:38 +0000292 case 9:
293 {
294 next_action.Relaunch(GetLaunchInfo());
295 break;
296 }
297
Greg Clayton7b8f7382013-03-18 22:34:00 +0000298 default:
299 {
300 next_action.Kill();
301 }
302 break;
Enrico Granataf58cece2013-03-08 20:29:13 +0000303 }
Enrico Granataf58cece2013-03-08 20:29:13 +0000304 }
305
Greg Clayton880afc52013-03-22 02:31:35 +0000306 virtual void
307 WriteResults (Results &results)
Enrico Granataf58cece2013-03-08 20:29:13 +0000308 {
Greg Clayton880afc52013-03-22 02:31:35 +0000309 m_fetch_frames_measurement.WriteAverageValue(results);
310 m_file_line_bp_measurement.WriteAverageValue(results);
311 m_fetch_modules_measurement.WriteAverageValue(results);
312 m_fetch_vars_measurement.WriteAverageValue(results);
313 m_run_expr_measurement.WriteAverageValue(results);
Enrico Granata85e9d6d2013-04-12 21:31:02 +0000314 results.Write(GetResultFilePath());
Enrico Granataf58cece2013-03-08 20:29:13 +0000315 }
316
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000317 void
318 SetExecutablePath (const char* str)
319 {
320 if (str)
321 m_app_path.assign(str);
322 }
323
324 const char*
325 GetExecutablePath ()
326 {
327 if (m_app_path.empty())
328 return NULL;
329 return m_app_path.c_str();
330 }
331
332 void
333 SetDocumentPath (const char* str)
334 {
335 if (str)
336 m_doc_path.assign(str);
337 }
338
339 const char*
340 GetDocumentPath ()
341 {
342 if (m_doc_path.empty())
343 return NULL;
344 return m_doc_path.c_str();
345 }
346
347
348 void
349 SetResultFilePath (const char* str)
350 {
351 if (str)
352 m_out_path.assign(str);
353 }
354
355 const char*
356 GetResultFilePath ()
357 {
358 if (m_out_path.empty())
Enrico Granata85e9d6d2013-04-12 21:31:02 +0000359 return "/dev/stdout";
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000360 return m_out_path.c_str();
361 }
362
Enrico Granata85e9d6d2013-04-12 21:31:02 +0000363 bool
364 GetPrintHelp ()
365 {
366 return m_print_help;
367 }
368
Enrico Granataf58cece2013-03-08 20:29:13 +0000369private:
Greg Clayton1080faf2013-03-19 19:30:33 +0000370 Measurement<lldb_perf::TimeGauge, std::function<void()>> m_fetch_frames_measurement;
371 Measurement<lldb_perf::TimeGauge, std::function<void(const char*, uint32_t)>> m_file_line_bp_measurement;
372 Measurement<lldb_perf::TimeGauge, std::function<void()>> m_fetch_modules_measurement;
373 Measurement<lldb_perf::TimeGauge, std::function<void(int)>> m_fetch_vars_measurement;
374 Measurement<lldb_perf::TimeGauge, std::function<void(SBFrame, const char*)>> m_run_expr_measurement;
Enrico Granataf58cece2013-03-08 20:29:13 +0000375
Enrico Granataf58cece2013-03-08 20:29:13 +0000376 std::string m_app_path;
377 std::string m_doc_path;
378 std::string m_out_path;
Enrico Granata85e9d6d2013-04-12 21:31:02 +0000379 bool m_print_help;
Enrico Granataf58cece2013-03-08 20:29:13 +0000380};
381
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000382int main(int argc, const char * argv[])
383{
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000384 SketchTest test;
Enrico Granata85e9d6d2013-04-12 21:31:02 +0000385 return TestCase::Run(test, argc, argv);
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000386}