From f58cececaaee321143b177a0d7cbbffddcbfea4c Mon Sep 17 00:00:00 2001 From: Enrico Granata Date: Fri, 8 Mar 2013 20:29:13 +0000 Subject: Initial checkin of a new project: LLDB Performance Testing Infrastructure This is a very basic implementation of a library that easily allows to drive LLDB.framework to write test cases for performance This is separate from the LLDB testsuite in test/ in that: a) this uses C++ instead of Python to avoid measures being affected by SWIG b) this is in very early development and needs lots of tweaking before it can be considered functionally complete c) this is not meant to test correctness but to help catch performance regressions There is a sample application built against the library (in darwin/sketch) that uses the famous sample app Sketch as an inferior to measure certain basic parameters of LLDB's behavior. The resulting output is a PLIST much like the following: fetch-frames 0.13161715522222225 file-line-bkpt 0.029111678750000002 fetch-modules 0.00026376766666666668 fetch-vars 0.17820429311111111 run-expr 0.029676525769230768 Areas for improvement: - code cleanups (I will be out of the office for a couple days this coming week, but please keep ideas coming!) - more metrics and test cases - better error checking This toolkit also comprises a simple event-loop-driven controller for LLDB, similar yet much simpler to what the Driver does to implement the lldb command-line tool. llvm-svn: 176715 --- lldb/tools/lldb-perf/lib/TestCase.cpp | 178 ++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 lldb/tools/lldb-perf/lib/TestCase.cpp (limited to 'lldb/tools/lldb-perf/lib/TestCase.cpp') diff --git a/lldb/tools/lldb-perf/lib/TestCase.cpp b/lldb/tools/lldb-perf/lib/TestCase.cpp new file mode 100644 index 00000000000..2067969f81a --- /dev/null +++ b/lldb/tools/lldb-perf/lib/TestCase.cpp @@ -0,0 +1,178 @@ +// +// TestCase.cpp +// PerfTestDriver +// +// Created by Enrico Granata on 3/7/13. +// Copyright (c) 2013 Apple Inc. All rights reserved. +// + +#include "TestCase.h" +#include "Xcode.h" + +using namespace lldb::perf; + +TestCase::TestCase () : +m_debugger(), +m_target(), +m_process(), +m_thread(), +m_listener(), +m_verbose(false) +{} + +void +TestCase::Setup (int argc, const char** argv) +{ + SBDebugger::Initialize(); + SBHostOS::ThreadCreated (""); + m_debugger = SBDebugger::Create(false); + m_listener = m_debugger.GetListener(); +} + +bool +TestCase::Launch (const char** args, const char* cwd) +{ + m_process = m_target.LaunchSimple(args,NULL,cwd); + m_process.GetBroadcaster().AddListener(m_listener, SBProcess::eBroadcastBitStateChanged | SBProcess::eBroadcastBitInterrupt); + return m_process.IsValid (); +} + +void +TestCase::SetVerbose (bool b) +{ + m_verbose = b; +} + +bool +TestCase::GetVerbose () +{ + return m_verbose; +} + +void +TestCase::Loop () +{ + int step = 0; + SBEvent evt; + while (true) + { + m_listener.WaitForEvent (UINT32_MAX,evt); + StateType state = SBProcess::GetStateFromEvent (evt); + if (m_verbose) + printf("event = %s\n",SBDebugger::StateAsCString(state)); + if (SBProcess::GetRestartedFromEvent(evt)) + continue; + switch (state) + { + case eStateInvalid: + case eStateDetached: + case eStateCrashed: + case eStateUnloaded: + break; + case eStateExited: + return; + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + continue; + case eStateStopped: + case eStateSuspended: + { + bool fatal = false; + for (auto thread_index = 0; thread_index < m_process.GetNumThreads(); thread_index++) + { + SBThread thread(m_process.GetThreadAtIndex(thread_index)); + SBFrame frame(thread.GetFrameAtIndex(0)); + StopReason stop_reason = thread.GetStopReason(); + if (m_verbose) printf("tid = 0x%llx pc = 0x%llx ",thread.GetThreadID(),frame.GetPC()); + switch (stop_reason) + { + case eStopReasonNone: + if (m_verbose) printf("none\n"); + break; + + case eStopReasonTrace: + if (m_verbose) printf("trace\n"); + break; + + case eStopReasonPlanComplete: + if (m_verbose) printf("plan complete\n"); + break; + case eStopReasonThreadExiting: + if (m_verbose) printf("thread exiting\n"); + break; + case eStopReasonExec: + if (m_verbose) printf("exec\n"); + break; + case eStopReasonInvalid: + if (m_verbose) printf("invalid\n"); + break; + case eStopReasonException: + if (m_verbose) printf("exception\n"); + fatal = true; + break; + case eStopReasonBreakpoint: + if (m_verbose) printf("breakpoint id = %lld.%lld\n",thread.GetStopReasonDataAtIndex(0),thread.GetStopReasonDataAtIndex(1)); + break; + case eStopReasonWatchpoint: + if (m_verbose) printf("watchpoint id = %lld\n",thread.GetStopReasonDataAtIndex(0)); + break; + case eStopReasonSignal: + if (m_verbose) printf("signal %d\n",(int)thread.GetStopReasonDataAtIndex(0)); + break; + } + } + if (fatal) + { + if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true); + exit(1); + } + if (m_verbose) + printf("RUNNING STEP %d\n",step); + auto action = TestStep(step); + step++; + switch (action.type) + { + case ActionWanted::Type::eAWContinue: + m_debugger.HandleCommand("continue"); + break; + case ActionWanted::Type::eAWFinish: + if (action.thread.IsValid() == false) + { + if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true); + if (m_verbose) printf("[finish invalid] I am gonna die at step %d\n",step); + exit(501); + } + m_process.SetSelectedThread(action.thread); + m_debugger.HandleCommand("finish"); + break; + case ActionWanted::Type::eAWNext: + if (action.thread.IsValid() == false) + { + if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true); + if (m_verbose) printf("[next invalid] I am gonna die at step %d\n",step); + exit(500); + } + m_process.SetSelectedThread(action.thread); + m_debugger.HandleCommand("next"); + break; + case ActionWanted::Type::eAWKill: + if (m_verbose) printf("I want to die\n"); + m_process.Kill(); + return; + } + } + } + } + if (GetVerbose()) printf("I am gonna die at step %d\n",step); +} + +void +TestCase::Run (TestCase& test, int argc, const char** argv) +{ + test.Setup(argc, argv); + test.Loop(); + test.Results(); +} -- cgit v1.2.3