Greg Clayton | 5dbe5d4 | 2013-03-21 03:39:51 +0000 | [diff] [blame] | 1 | //===-- sketch.cpp ----------------------------------------------*- C++ -*-===// |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 2 | // |
Greg Clayton | 5dbe5d4 | 2013-03-21 03:39:51 +0000 | [diff] [blame] | 3 | // The LLVM Compiler Infrastructure |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 4 | // |
Greg Clayton | 5dbe5d4 | 2013-03-21 03:39:51 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 7 | // |
Greg Clayton | 5dbe5d4 | 2013-03-21 03:39:51 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 9 | |
| 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 Granata | 4b4e24d | 2013-04-01 17:42:02 +0000 | [diff] [blame] | 21 | #include <getopt.h> |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 22 | |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 23 | using namespace lldb_perf; |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 24 | |
Enrico Granata | 85e9d6d | 2013-04-12 21:31:02 +0000 | [diff] [blame] | 25 | static 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 Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 33 | class SketchTest : public TestCase |
| 34 | { |
| 35 | public: |
| 36 | SketchTest () : |
Greg Clayton | 1080faf | 2013-03-19 19:30:33 +0000 | [diff] [blame] | 37 | 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 Granata | 85e9d6d | 2013-04-12 21:31:02 +0000 | [diff] [blame] | 65 | { |
| 66 | m_app_path.clear(); |
| 67 | m_out_path.clear(); |
| 68 | m_doc_path.clear(); |
| 69 | m_print_help = false; |
| 70 | } |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 71 | |
| 72 | virtual |
| 73 | ~SketchTest () |
| 74 | { |
| 75 | } |
| 76 | |
Greg Clayton | e0b924e | 2013-03-19 04:41:22 +0000 | [diff] [blame] | 77 | virtual bool |
Enrico Granata | 85e9d6d | 2013-04-12 21:31:02 +0000 | [diff] [blame] | 78 | 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 Granata | 8fab9fd | 2013-04-01 18:02:25 +0000 | [diff] [blame] | 136 | Setup (int& argc, const char**& argv) |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 137 | { |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 138 | TestCase::Setup(argc,argv); |
Enrico Granata | 85e9d6d | 2013-04-12 21:31:02 +0000 | [diff] [blame] | 139 | 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 Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 174 | lldb::SBLaunchInfo launch_info = GetLaunchInfo(); |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 175 | m_target = m_debugger.CreateTarget(m_app_path.c_str()); |
Greg Clayton | 1080faf | 2013-03-19 19:30:33 +0000 | [diff] [blame] | 176 | 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 Clayton | e0b924e | 2013-03-19 04:41:22 +0000 | [diff] [blame] | 179 | return Launch (launch_info); |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 180 | } |
| 181 | |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 182 | 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 Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 193 | void |
| 194 | DoTest () |
| 195 | { |
Greg Clayton | 1080faf | 2013-03-19 19:30:33 +0000 | [diff] [blame] | 196 | m_fetch_frames_measurement(); |
| 197 | m_fetch_modules_measurement(); |
| 198 | m_fetch_vars_measurement(1); |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 199 | } |
| 200 | |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 201 | virtual void |
| 202 | TestStep (int counter, ActionWanted &next_action) |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 203 | { |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 204 | switch (counter) |
| 205 | { |
| 206 | case 0: |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 207 | case 10: |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 208 | { |
| 209 | DoTest (); |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 210 | if (counter == 0) |
| 211 | m_file_line_bp_measurement("SKTDocument.m",254); |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 212 | next_action.Continue(); |
| 213 | } |
| 214 | break; |
| 215 | |
| 216 | case 1: |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 217 | case 11: |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 218 | { |
| 219 | DoTest (); |
Greg Clayton | e0b924e | 2013-03-19 04:41:22 +0000 | [diff] [blame] | 220 | 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 Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 225 | next_action.Continue(); |
| 226 | } |
| 227 | break; |
| 228 | |
| 229 | case 2: |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 230 | case 12: |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 231 | { |
| 232 | DoTest (); |
| 233 | next_action.Continue(); |
| 234 | } |
| 235 | break; |
| 236 | |
| 237 | case 3: |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 238 | case 13: |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 239 | { |
| 240 | DoTest (); |
Greg Clayton | e0b924e | 2013-03-19 04:41:22 +0000 | [diff] [blame] | 241 | next_action.StepOver(m_thread); |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 242 | } |
| 243 | break; |
| 244 | |
| 245 | case 4: |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 246 | case 14: |
| 247 | |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 248 | { |
| 249 | DoTest (); |
Greg Clayton | e0b924e | 2013-03-19 04:41:22 +0000 | [diff] [blame] | 250 | 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 Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 253 | } |
| 254 | break; |
| 255 | |
| 256 | case 5: |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 257 | case 15: |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 258 | { |
| 259 | DoTest (); |
Greg Clayton | e0b924e | 2013-03-19 04:41:22 +0000 | [diff] [blame] | 260 | next_action.StepOver(m_thread); |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 261 | } |
| 262 | break; |
| 263 | |
| 264 | case 6: |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 265 | case 16: |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 266 | { |
| 267 | DoTest (); |
Greg Clayton | e0b924e | 2013-03-19 04:41:22 +0000 | [diff] [blame] | 268 | next_action.StepOver(m_thread); |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 269 | } |
| 270 | break; |
| 271 | |
| 272 | case 7: |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 273 | case 17: |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 274 | { |
| 275 | DoTest (); |
Greg Clayton | e0b924e | 2013-03-19 04:41:22 +0000 | [diff] [blame] | 276 | 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 Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 280 | } |
| 281 | break; |
| 282 | |
| 283 | case 8: |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 284 | case 18: |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 285 | { |
| 286 | DoTest (); |
Greg Clayton | e0b924e | 2013-03-19 04:41:22 +0000 | [diff] [blame] | 287 | 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 Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 290 | } |
| 291 | break; |
Enrico Granata | a571e21 | 2013-04-15 19:07:38 +0000 | [diff] [blame^] | 292 | case 9: |
| 293 | { |
| 294 | next_action.Relaunch(GetLaunchInfo()); |
| 295 | break; |
| 296 | } |
| 297 | |
Greg Clayton | 7b8f738 | 2013-03-18 22:34:00 +0000 | [diff] [blame] | 298 | default: |
| 299 | { |
| 300 | next_action.Kill(); |
| 301 | } |
| 302 | break; |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 303 | } |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 304 | } |
| 305 | |
Greg Clayton | 880afc5 | 2013-03-22 02:31:35 +0000 | [diff] [blame] | 306 | virtual void |
| 307 | WriteResults (Results &results) |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 308 | { |
Greg Clayton | 880afc5 | 2013-03-22 02:31:35 +0000 | [diff] [blame] | 309 | 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 Granata | 85e9d6d | 2013-04-12 21:31:02 +0000 | [diff] [blame] | 314 | results.Write(GetResultFilePath()); |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 315 | } |
| 316 | |
Enrico Granata | 4b4e24d | 2013-04-01 17:42:02 +0000 | [diff] [blame] | 317 | 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 Granata | 85e9d6d | 2013-04-12 21:31:02 +0000 | [diff] [blame] | 359 | return "/dev/stdout"; |
Enrico Granata | 4b4e24d | 2013-04-01 17:42:02 +0000 | [diff] [blame] | 360 | return m_out_path.c_str(); |
| 361 | } |
| 362 | |
Enrico Granata | 85e9d6d | 2013-04-12 21:31:02 +0000 | [diff] [blame] | 363 | bool |
| 364 | GetPrintHelp () |
| 365 | { |
| 366 | return m_print_help; |
| 367 | } |
| 368 | |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 369 | private: |
Greg Clayton | 1080faf | 2013-03-19 19:30:33 +0000 | [diff] [blame] | 370 | 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 Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 375 | |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 376 | std::string m_app_path; |
| 377 | std::string m_doc_path; |
| 378 | std::string m_out_path; |
Enrico Granata | 85e9d6d | 2013-04-12 21:31:02 +0000 | [diff] [blame] | 379 | bool m_print_help; |
Enrico Granata | f58cece | 2013-03-08 20:29:13 +0000 | [diff] [blame] | 380 | }; |
| 381 | |
Enrico Granata | 4b4e24d | 2013-04-01 17:42:02 +0000 | [diff] [blame] | 382 | int main(int argc, const char * argv[]) |
| 383 | { |
Enrico Granata | 4b4e24d | 2013-04-01 17:42:02 +0000 | [diff] [blame] | 384 | SketchTest test; |
Enrico Granata | 85e9d6d | 2013-04-12 21:31:02 +0000 | [diff] [blame] | 385 | return TestCase::Run(test, argc, argv); |
Enrico Granata | 4b4e24d | 2013-04-01 17:42:02 +0000 | [diff] [blame] | 386 | } |