blob: 361fcda8ac6e99c6ce9377ead26e70788277cad3 [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
25class SketchTest : public TestCase
26{
27public:
28 SketchTest () :
Greg Clayton1080faf2013-03-19 19:30:33 +000029 m_fetch_frames_measurement ([this] () -> void
30 {
31 Xcode::FetchFrames (GetProcess(),false,false);
32 }, "fetch-frames", "time to dump backtrace for every frame in every thread"),
33 m_file_line_bp_measurement([this] (const char* file, uint32_t line) -> void
34 {
35 Xcode::CreateFileLineBreakpoint(GetTarget(), file, line);
36 }, "file-line-bkpt", "time to set a breakpoint given a file and line"),
37 m_fetch_modules_measurement ([this] () -> void
38 {
39 Xcode::FetchModules(GetTarget());
40 }, "fetch-modules", "time to get info for all modules in the process"),
41 m_fetch_vars_measurement([this] (int depth) -> void
42 {
43 SBProcess process (GetProcess());
44 auto threads_count = process.GetNumThreads();
45 for (size_t thread_num = 0; thread_num < threads_count; thread_num++)
46 {
47 SBThread thread(process.GetThreadAtIndex(thread_num));
48 SBFrame frame(thread.GetFrameAtIndex(0));
49 Xcode::FetchVariables(frame,depth,GetVerbose());
50 }
51 }, "fetch-vars", "time to dump variables for the topmost frame in every thread"),
52 m_run_expr_measurement([this] (SBFrame frame, const char* expr) -> void
53 {
54 SBValue value(frame.EvaluateExpression(expr, lldb::eDynamicCanRunTarget));
55 Xcode::FetchVariable (value, 0, GetVerbose());
56 }, "run-expr", "time to evaluate an expression and display the result")
Enrico Granataf58cece2013-03-08 20:29:13 +000057 {}
58
59 virtual
60 ~SketchTest ()
61 {
62 }
63
Greg Claytone0b924e2013-03-19 04:41:22 +000064 virtual bool
Enrico Granata8fab9fd2013-04-01 18:02:25 +000065 Setup (int& argc, const char**& argv)
Enrico Granataf58cece2013-03-08 20:29:13 +000066 {
Greg Clayton1080faf2013-03-19 19:30:33 +000067 //SetVerbose(true);
Enrico Granata86910572013-03-14 19:00:42 +000068 m_app_path.assign(argv[1]);
69 m_doc_path.assign(argv[2]);
Enrico Granataf58cece2013-03-08 20:29:13 +000070 m_out_path.assign(argv[3]);
71 TestCase::Setup(argc,argv);
72 m_target = m_debugger.CreateTarget(m_app_path.c_str());
73 const char* file_arg = m_doc_path.c_str();
74 const char* persist_arg = "-ApplePersistenceIgnoreState";
75 const char* persist_skip = "YES";
76 const char* empty = nullptr;
77 const char* args[] = {file_arg,persist_arg,persist_skip,empty};
Greg Claytone0b924e2013-03-19 04:41:22 +000078 SBLaunchInfo launch_info (args);
Greg Clayton1080faf2013-03-19 19:30:33 +000079 m_file_line_bp_measurement("SKTDocument.m",245);
80 m_file_line_bp_measurement("SKTDocument.m",283);
81 m_file_line_bp_measurement("SKTText.m",326);
Greg Claytone0b924e2013-03-19 04:41:22 +000082 return Launch (launch_info);
Enrico Granataf58cece2013-03-08 20:29:13 +000083 }
84
85 void
86 DoTest ()
87 {
Greg Clayton1080faf2013-03-19 19:30:33 +000088 m_fetch_frames_measurement();
89 m_fetch_modules_measurement();
90 m_fetch_vars_measurement(1);
Enrico Granataf58cece2013-03-08 20:29:13 +000091 }
92
Greg Clayton7b8f7382013-03-18 22:34:00 +000093 virtual void
94 TestStep (int counter, ActionWanted &next_action)
Enrico Granataf58cece2013-03-08 20:29:13 +000095 {
Greg Clayton7b8f7382013-03-18 22:34:00 +000096 switch (counter)
97 {
98 case 0:
99 {
100 DoTest ();
Greg Clayton1080faf2013-03-19 19:30:33 +0000101 m_file_line_bp_measurement("SKTDocument.m",254);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000102 next_action.Continue();
103 }
104 break;
105
106 case 1:
107 {
108 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000109 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"properties");
110 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[properties description]");
111 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"typeName");
112 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"data");
113 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[data description]");
Greg Clayton7b8f7382013-03-18 22:34:00 +0000114 next_action.Continue();
115 }
116 break;
117
118 case 2:
119 {
120 DoTest ();
121 next_action.Continue();
122 }
123 break;
124
125 case 3:
126 {
127 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000128 next_action.StepOver(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000129 }
130 break;
131
132 case 4:
133 {
134 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000135 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"layoutManager");
136 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"contents");
137 next_action.StepOver(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000138 }
139 break;
140
141 case 5:
142 {
143 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000144 next_action.StepOver(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000145 }
146 break;
147
148 case 6:
149 {
150 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000151 next_action.StepOver(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000152 }
153 break;
154
155 case 7:
156 {
157 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000158 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"@\"an NSString\"");
159 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[(id)@\"an NSString\" description]");
160 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"@[@1,@2,@3]");
161 next_action.StepOut(m_thread);
Greg Clayton7b8f7382013-03-18 22:34:00 +0000162 }
163 break;
164
165 case 8:
166 {
167 DoTest ();
Greg Claytone0b924e2013-03-19 04:41:22 +0000168 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[graphics description]");
169 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[selectionIndexes description]");
170 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"(BOOL)NSIntersectsRect(rect, graphicDrawingBounds)");
Greg Clayton7b8f7382013-03-18 22:34:00 +0000171 next_action.Kill();
172 }
173 break;
174
175 default:
176 {
177 next_action.Kill();
178 }
179 break;
Enrico Granataf58cece2013-03-08 20:29:13 +0000180 }
Enrico Granataf58cece2013-03-08 20:29:13 +0000181 }
182
Greg Clayton880afc52013-03-22 02:31:35 +0000183 virtual void
184 WriteResults (Results &results)
Enrico Granataf58cece2013-03-08 20:29:13 +0000185 {
Greg Clayton880afc52013-03-22 02:31:35 +0000186 m_fetch_frames_measurement.WriteAverageValue(results);
187 m_file_line_bp_measurement.WriteAverageValue(results);
188 m_fetch_modules_measurement.WriteAverageValue(results);
189 m_fetch_vars_measurement.WriteAverageValue(results);
190 m_run_expr_measurement.WriteAverageValue(results);
191 results.Write(m_out_path.c_str());
Enrico Granataf58cece2013-03-08 20:29:13 +0000192 }
193
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000194 void
195 SetExecutablePath (const char* str)
196 {
197 if (str)
198 m_app_path.assign(str);
199 }
200
201 const char*
202 GetExecutablePath ()
203 {
204 if (m_app_path.empty())
205 return NULL;
206 return m_app_path.c_str();
207 }
208
209 void
210 SetDocumentPath (const char* str)
211 {
212 if (str)
213 m_doc_path.assign(str);
214 }
215
216 const char*
217 GetDocumentPath ()
218 {
219 if (m_doc_path.empty())
220 return NULL;
221 return m_doc_path.c_str();
222 }
223
224
225 void
226 SetResultFilePath (const char* str)
227 {
228 if (str)
229 m_out_path.assign(str);
230 }
231
232 const char*
233 GetResultFilePath ()
234 {
235 if (m_out_path.empty())
236 return NULL;
237 return m_out_path.c_str();
238 }
239
Enrico Granataf58cece2013-03-08 20:29:13 +0000240private:
Greg Clayton1080faf2013-03-19 19:30:33 +0000241 Measurement<lldb_perf::TimeGauge, std::function<void()>> m_fetch_frames_measurement;
242 Measurement<lldb_perf::TimeGauge, std::function<void(const char*, uint32_t)>> m_file_line_bp_measurement;
243 Measurement<lldb_perf::TimeGauge, std::function<void()>> m_fetch_modules_measurement;
244 Measurement<lldb_perf::TimeGauge, std::function<void(int)>> m_fetch_vars_measurement;
245 Measurement<lldb_perf::TimeGauge, std::function<void(SBFrame, const char*)>> m_run_expr_measurement;
Enrico Granataf58cece2013-03-08 20:29:13 +0000246
Enrico Granataf58cece2013-03-08 20:29:13 +0000247 std::string m_app_path;
248 std::string m_doc_path;
249 std::string m_out_path;
250};
251
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000252struct Options
Enrico Granataf58cece2013-03-08 20:29:13 +0000253{
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000254 std::string sketch_path;
255 std::string foobar_path;
256 std::string out_file;
257 bool verbose;
258 bool error;
259 bool print_help;
260
261 Options() :
262 verbose (false),
263 error (false),
264 print_help (false)
265 {
266 }
267};
268
269static struct option g_long_options[] = {
270 { "verbose", no_argument, NULL, 'v' },
271 { "sketch", required_argument, NULL, 'c' },
272 { "foobar", required_argument, NULL, 'f' },
273 { "out-file", required_argument, NULL, 'o' },
274 { NULL, 0, NULL, 0 }
275};
276
277
278std::string
279GetShortOptionString (struct option *long_options)
280{
281 std::string option_string;
282 for (int i = 0; long_options[i].name != NULL; ++i)
283 {
284 if (long_options[i].flag == NULL)
285 {
286 option_string.push_back ((char) long_options[i].val);
287 switch (long_options[i].has_arg)
288 {
289 default:
290 case no_argument:
291 break;
292 case required_argument:
293 option_string.push_back (':');
294 break;
295 case optional_argument:
296 option_string.append (2, ':');
297 break;
298 }
299 }
300 }
301 return option_string;
Enrico Granataf58cece2013-03-08 20:29:13 +0000302}
303
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000304int main(int argc, const char * argv[])
305{
306
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000307 // Prepare for & make calls to getopt_long_only.
Enrico Granata4b4e24d2013-04-01 17:42:02 +0000308
309 SketchTest test;
310
311 std::string short_option_string (GetShortOptionString(g_long_options));
312
313 Options option_data;
314 bool done = false;
315
316#if __GLIBC__
317 optind = 0;
318#else
319 optreset = 1;
320 optind = 1;
321#endif
322 while (!done)
323 {
324 int long_options_index = -1;
325 const int short_option = ::getopt_long_only (argc,
326 const_cast<char **>(argv),
327 short_option_string.c_str(),
328 g_long_options,
329 &long_options_index);
330
331 switch (short_option)
332 {
333 case 0:
334 // Already handled
335 break;
336
337 case -1:
338 done = true;
339 break;
340
341 case '?':
342 option_data.print_help = true;
343 break;
344
345 case 'h':
346 option_data.print_help = true;
347 break;
348
349 case 'v':
350 option_data.verbose = true;
351 break;
352
353 case 'c':
354 {
355 SBFileSpec file(optarg);
356 if (file.Exists())
357 test.SetExecutablePath(optarg);
358 else
359 fprintf(stderr, "error: file specified in --sketch (-c) option doesn't exist: '%s'\n", optarg);
360 }
361 break;
362
363 case 'f':
364 {
365 SBFileSpec file(optarg);
366 if (file.Exists())
367 test.SetDocumentPath(optarg);
368 else
369 fprintf(stderr, "error: file specified in --foobar (-f) option doesn't exist: '%s'\n", optarg);
370 }
371 break;
372
373 case 'o':
374 test.SetResultFilePath(optarg);
375 break;
376
377 default:
378 option_data.error = true;
379 option_data.print_help = true;
380 fprintf (stderr, "error: unrecognized option %c\n", short_option);
381 break;
382 }
383 }
384
385
386 if (test.GetExecutablePath() == NULL)
387 {
388 // --sketch is mandatory
389 option_data.print_help = true;
390 option_data.error = true;
391 fprintf (stderr, "error: the '--sketch=PATH' option is mandatory\n");
392 }
393
394 if (test.GetDocumentPath() == NULL)
395 {
396 // --foobar is mandatory
397 option_data.print_help = true;
398 option_data.error = true;
399 fprintf (stderr, "error: the '--foobar=PATH' option is mandatory\n");
400 }
401
402 if (option_data.print_help)
403 {
404 puts(R"(
405 NAME
406 lldb_perf_sketch -- a tool that measures LLDB peformance while debugging sketch.
407
408 SYNOPSIS
409 lldb_perf_sketch --sketch=PATH --foobar=PATH [--out-file=PATH --verbose]
410
411 DESCRIPTION
412 Runs a set of static timing and memory tasks against sketch and outputs results
413 to a plist file.
414 )");
415 }
416 if (option_data.error)
417 {
418 exit(1);
419 }
420
421 // Update argc and argv after parsing options
422 argc -= optind;
423 argv += optind;
424
425 test.SetVerbose(option_data.verbose);
426 TestCase::Run(test, argc, argv);
427 return 0;
428}