sketch.cpp revision ec87e5c098f1ce1c9182d1c5438e0beca0996597
1//===-- sketch.cpp ----------------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 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> 21#include <getopt.h> 22 23using namespace lldb_perf; 24 25static 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 33class SketchTest : public TestCase 34{ 35public: 36 SketchTest () : 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") 65 { 66 m_app_path.clear(); 67 m_out_path.clear(); 68 m_doc_path.clear(); 69 m_print_help = false; 70 } 71 72 virtual 73 ~SketchTest () 74 { 75 } 76 77 virtual bool 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 136 Setup (int& argc, const char**& argv) 137 { 138 TestCase::Setup(argc,argv); 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 } 174 lldb::SBLaunchInfo launch_info = GetLaunchInfo(); 175 m_target = m_debugger.CreateTarget(m_app_path.c_str()); 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); 179 return Launch (launch_info); 180 } 181 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 193 void 194 DoTest () 195 { 196 m_fetch_frames_measurement(); 197 m_fetch_modules_measurement(); 198 m_fetch_vars_measurement(1); 199 } 200 201 virtual void 202 TestStep (int counter, ActionWanted &next_action) 203 { 204 switch (counter) 205 { 206 case 0: 207 case 10: 208 case 20: 209 { 210 DoTest (); 211 if (counter == 0) 212 m_file_line_bp_measurement("SKTDocument.m",254); 213 next_action.Continue(); 214 } 215 break; 216 217 case 1: 218 case 11: 219 case 21: 220 { 221 DoTest (); 222 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"properties"); 223 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[properties description]"); 224 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"typeName"); 225 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"data"); 226 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[data description]"); 227 next_action.Continue(); 228 } 229 break; 230 231 case 2: 232 case 12: 233 case 22: 234 { 235 DoTest (); 236 next_action.Continue(); 237 } 238 break; 239 240 case 3: 241 case 13: 242 case 23: 243 { 244 DoTest (); 245 next_action.StepOver(m_thread); 246 } 247 break; 248 249 case 4: 250 case 14: 251 case 24: 252 253 { 254 DoTest (); 255 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"layoutManager"); 256 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"contents"); 257 next_action.StepOver(m_thread); 258 } 259 break; 260 261 case 5: 262 case 15: 263 case 25: 264 { 265 DoTest (); 266 next_action.StepOver(m_thread); 267 } 268 break; 269 270 case 6: 271 case 16: 272 case 26: 273 { 274 DoTest (); 275 next_action.StepOver(m_thread); 276 } 277 break; 278 279 case 7: 280 case 17: 281 case 27: 282 { 283 DoTest (); 284 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"@\"an NSString\""); 285 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[(id)@\"an NSString\" description]"); 286 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"@[@1,@2,@3]"); 287 next_action.StepOut(m_thread); 288 } 289 break; 290 291 case 8: 292 case 18: 293 case 28: 294 { 295 DoTest (); 296 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[graphics description]"); 297 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[selectionIndexes description]"); 298 m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"(BOOL)NSIntersectsRect(rect, graphicDrawingBounds)"); 299 } 300 break; 301 case 9: 302 case 19: 303 { 304 next_action.Relaunch(GetLaunchInfo()); 305 break; 306 } 307 308 default: 309 { 310 next_action.Kill(); 311 } 312 break; 313 } 314 } 315 316 virtual void 317 WriteResults (Results &results) 318 { 319 m_fetch_frames_measurement.WriteAverageAndStandardDeviation(results); 320 m_file_line_bp_measurement.WriteAverageAndStandardDeviation(results); 321 m_fetch_modules_measurement.WriteAverageAndStandardDeviation(results); 322 m_fetch_vars_measurement.WriteAverageAndStandardDeviation(results); 323 m_run_expr_measurement.WriteAverageAndStandardDeviation(results); 324 results.Write(GetResultFilePath()); 325 } 326 327 void 328 SetExecutablePath (const char* str) 329 { 330 if (str) 331 m_app_path.assign(str); 332 } 333 334 const char* 335 GetExecutablePath () 336 { 337 if (m_app_path.empty()) 338 return NULL; 339 return m_app_path.c_str(); 340 } 341 342 void 343 SetDocumentPath (const char* str) 344 { 345 if (str) 346 m_doc_path.assign(str); 347 } 348 349 const char* 350 GetDocumentPath () 351 { 352 if (m_doc_path.empty()) 353 return NULL; 354 return m_doc_path.c_str(); 355 } 356 357 358 void 359 SetResultFilePath (const char* str) 360 { 361 if (str) 362 m_out_path.assign(str); 363 } 364 365 const char* 366 GetResultFilePath () 367 { 368 if (m_out_path.empty()) 369 return "/dev/stdout"; 370 return m_out_path.c_str(); 371 } 372 373 bool 374 GetPrintHelp () 375 { 376 return m_print_help; 377 } 378 379private: 380 Measurement<lldb_perf::TimeGauge, std::function<void()>> m_fetch_frames_measurement; 381 Measurement<lldb_perf::TimeGauge, std::function<void(const char*, uint32_t)>> m_file_line_bp_measurement; 382 Measurement<lldb_perf::TimeGauge, std::function<void()>> m_fetch_modules_measurement; 383 Measurement<lldb_perf::TimeGauge, std::function<void(int)>> m_fetch_vars_measurement; 384 Measurement<lldb_perf::TimeGauge, std::function<void(SBFrame, const char*)>> m_run_expr_measurement; 385 386 std::string m_app_path; 387 std::string m_doc_path; 388 std::string m_out_path; 389 bool m_print_help; 390}; 391 392int main(int argc, const char * argv[]) 393{ 394 SketchTest test; 395 return TestCase::Run(test, argc, argv); 396} 397