Much more cleanup on the performance testing infrastructure:
authorGreg Clayton <gclayton@apple.com>
Fri, 22 Mar 2013 02:31:35 +0000 (02:31 +0000)
committerGreg Clayton <gclayton@apple.com>
Fri, 22 Mar 2013 02:31:35 +0000 (02:31 +0000)
- Added new abtract Results class to keep CoreFoundation out of the tests. There are many subclasses for different settings:
    Results::Result::Dictionary
    Results::Result::Array
    Results::Result::Unsigned
    Results::Result::Double
    Results::Result::String
- Gauge<T> can now write themselves out via a templatized write to results function:
    template <class T>
    Results::ResultSP GetResult (const char *description, T value);

- There are four specializations of this so far:
    template <>
    Results::ResultSP GetResult (const char *description, double value);

    template <>
    Results::ResultSP GetResult (const char *description, uint64_t value);

    template <>
    Results::ResultSP GetResult (const char *description, std::string value);

    template <>
    Results::ResultSP GetResult (const char *description, MemoryStats value);
- Don't emit the virtual memory reading from the task info call as it really doesn't mean much as it includes way too much (shared cache + other stuff we don't have control over)
- Fixed other test cases to build correctly and use the new classes

llvm-svn: 177696

19 files changed:
lldb/tools/lldb-perf/common/clang/build-clang.sh
lldb/tools/lldb-perf/common/clang/lldb_perf_clang.cpp
lldb/tools/lldb-perf/common/stepping/lldb-perf-stepping.cpp
lldb/tools/lldb-perf/darwin/formatters/formatters.cpp
lldb/tools/lldb-perf/darwin/sketch/sketch.cpp
lldb/tools/lldb-perf/lib/Gauge.cpp [new file with mode: 0644]
lldb/tools/lldb-perf/lib/Gauge.h
lldb/tools/lldb-perf/lib/Measurement.h
lldb/tools/lldb-perf/lib/MemoryGauge.cpp
lldb/tools/lldb-perf/lib/MemoryGauge.h
lldb/tools/lldb-perf/lib/Metric.cpp
lldb/tools/lldb-perf/lib/Metric.h
lldb/tools/lldb-perf/lib/Results.cpp [new file with mode: 0644]
lldb/tools/lldb-perf/lib/Results.h [new file with mode: 0644]
lldb/tools/lldb-perf/lib/TestCase.cpp
lldb/tools/lldb-perf/lib/TestCase.h
lldb/tools/lldb-perf/lib/Timer.cpp
lldb/tools/lldb-perf/lib/Timer.h
lldb/tools/lldb-perf/lldbperf.xcodeproj/project.pbxproj

index 9506b43..5636801 100755 (executable)
@@ -1,10 +1,26 @@
 #!/bin/bash
 
-mkdir llvm-build
+if [ -d "llvm-build" ]; then
+    echo "Using existing 'llvm-build' directory..."    
+else
+    mkdir llvm-build
+fi
+
 cd llvm-build
-svn co --revision 176809 http://llvm.org/svn/llvm-project/llvm/trunk llvm
-( cd llvm/tools ; svn co --revision 176809 http://llvm.org/svn/llvm-project/cfe/trunk clang )
-mkdir build
-cd build
-../llvm/configure --enable-targets=x86_64,arm --build=x86_64-apple-darwin10 --enable-optimized --disable-assertions
-make -j8
+
+if [ -d "llvm" ]; then
+    echo "Using existing 'llvm' directory..."
+else
+    svn co --revision 176809 http://llvm.org/svn/llvm-project/llvm/trunk llvm
+    ( cd llvm/tools ; svn co --revision 176809 http://llvm.org/svn/llvm-project/cfe/trunk clang )
+fi
+
+if [ ! -d "build" ]; then
+    mkdir build
+    cd build
+    ../llvm/configure --enable-targets=x86_64,arm --build=x86_64-apple-darwin10 --disable-optimized --disable-assertions --enable-libcpp
+    make -j8 DEBUG_SYMBOLS=1
+fi
+
+
+
index e7610f5..9048a97 100644 (file)
@@ -7,14 +7,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <CoreFoundation/CoreFoundation.h>
-
 #include "lldb-perf/lib/Timer.h"
 #include "lldb-perf/lib/Metric.h"
 #include "lldb-perf/lib/Measurement.h"
+#include "lldb-perf/lib/Results.h"
 #include "lldb-perf/lib/TestCase.h"
 #include "lldb-perf/lib/Xcode.h"
-
 #include <iostream>
 #include <unistd.h>
 #include <fstream>
@@ -24,11 +22,15 @@ using namespace lldb_perf;
 class ClangTest : public TestCase
 {
 public:
-    ClangTest () : TestCase()
+    ClangTest () :
+        TestCase(),
+        m_set_bp_main_by_name(CreateTimeMeasurement([this] () -> void
+            {
+                m_target.BreakpointCreateByName("main");
+                m_target.BreakpointCreateByName("malloc");
+            }, "breakpoint1-relative-time", "Elapsed time to set a breakpoint at main by name, run and hit the breakpoint.")),
+        m_delta_memory("breakpoint1-memory-delta", "Memory increase that occurs due to setting a breakpoint at main by name.")
     {
-        m_set_bp_main_by_name = CreateTimeMeasurement([this] () -> void {
-            m_target.BreakpointCreateByName("main");
-        }, "break at \"main\"", "time set a breakpoint at main by name, run and hit the breakpoint");
     }
 
     virtual
@@ -39,13 +41,10 @@ public:
     virtual bool
        Setup (int argc, const char** argv)
     {
+        SetVerbose(true);
         m_app_path.assign(argv[1]);
         m_out_path.assign(argv[2]);
-        m_target = m_debugger.CreateTarget(m_app_path.c_str());
-        m_set_bp_main_by_name();
-        const char *clang_argv[] = { "clang --version", NULL };
-        SBLaunchInfo launch_info(clang_argv);
-        return Launch (launch_info);
+        return true;
     }
     
     void
@@ -59,71 +58,53 @@ public:
         switch (counter)
         {
             case 0:
-                m_target.BreakpointCreateByLocation("fmts_tester.mm", 68);
-                next_action.Continue();
+                {
+                    m_total_memory.Start();
+                    m_target = m_debugger.CreateTarget(m_app_path.c_str());
+                    const char *clang_argv[] = { "clang --version", NULL };
+                    m_delta_memory.Start();
+                    m_set_bp_main_by_name();
+                    m_delta_memory.Stop();
+                    SBLaunchInfo launch_info(clang_argv);
+                    Launch (launch_info);
+                }
                 break;
             case 1:
-                DoTest ();
-                next_action.Continue();
+                next_action.StepOver(m_thread);
                 break;
             case 2:
-                DoTest ();
-                next_action.Continue();
+                next_action.StepOver(m_thread);
                 break;
             case 3:
-                DoTest ();
-                next_action.Continue();
-                break;
-            case 4:
-                DoTest ();
-                next_action.Continue();
-                break;
-            case 5:
-                DoTest ();
-                next_action.Continue();
-                break;
-            case 6:
-                DoTest ();
-                next_action.Continue();
-                break;
-            case 7:
-                DoTest ();
-                next_action.Continue();
-                break;
-            case 8:
-                DoTest ();
-                next_action.Continue();
-                break;
-            case 9:
-                DoTest ();
-                next_action.Continue();
-                break;
-            case 10:
-                DoTest ();
-                next_action.Continue();
+                next_action.StepOver(m_thread);
                 break;
             default:
+                m_total_memory.Stop();
                 next_action.Kill();
                 break;
         }
     }
     
     void
-    Results ()
+    WriteResults (Results &results)
     {
-        CFCMutableArray array;
-        m_set_bp_main_by_name.Write(array);
-
-        CFDataRef xmlData = CFPropertyListCreateData(kCFAllocatorDefault, array.get(), kCFPropertyListXMLFormat_v1_0, 0, NULL);
+        Results::Dictionary& results_dict = results.GetDictionary();
         
-        CFURLRef file = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)m_out_path.c_str(), m_out_path.size(), FALSE);
+        m_set_bp_main_by_name.WriteAverageValue(results);
+        m_delta_memory.WriteAverageValue(results);
+
+        results_dict.Add ("breakpoint1-memory-total",
+                          "The total memory that the current process is using after setting the first breakpoint.",
+                          m_total_memory.GetStopValue().GetResult(NULL, NULL));
         
-        CFURLWriteDataAndPropertiesToResource(file,xmlData,NULL,NULL);
+        results.Write(m_out_path.c_str());
     }
     
 private:
     // C++ formatters
     TimeMeasurement<std::function<void()>> m_set_bp_main_by_name;
+    MemoryMeasurement<std::function<void()>> m_delta_memory;
+    MemoryGauge m_total_memory;
     std::string m_app_path;
     std::string m_out_path;
 
index 32ed38e..6bd0d21 100644 (file)
@@ -22,7 +22,7 @@ public:
     virtual
     ~StepTest() {}
     
-    virtual void
+    virtual bool
     Setup (int argc, const char **argv)
     {
         m_app_path.assign(argv[1]);
@@ -33,14 +33,29 @@ public:
         const char* file_arg = m_app_path.c_str();
         const char* empty = nullptr;
         const char* args[] = {file_arg, empty};
+        SBLaunchInfo launch_info (args);
         
-        Launch (args,".");
+        return Launch (launch_info);
     }
 
-private:
     void
     DoOneStep (int sequence)
     {
+        
+    }
+    
+
+    void
+    WriteResults (Results &results)
+    {
+//        results.Write(m_out_path.c_str());
+    }
+    
+
+private:
+    virtual void
+       TestStep (int counter, ActionWanted &next_action)
+    {
     
     }
     
@@ -61,7 +76,7 @@ int main(int argc, const char * argv[])
         return -1;
     }
     
-    StepTest skt;
-    TestCase::Run(skt,argc,argv);
+    StepTest test;
+    TestCase::Run(test,argc,argv);
     return 0;
 }
index 1a2f8e4..ff4931e 100644 (file)
@@ -197,27 +197,21 @@ public:
         }
     }
     
-    void
-    Results ()
+    virtual void
+    WriteResults (Results &results)
     {
-        CFCMutableArray array;
-        m_dump_std_vector_measurement.Write(array);
-        m_dump_std_list_measurement.Write(array);
-        m_dump_std_map_measurement.Write(array);
-        m_dump_std_string_measurement.Write(array);
-
-        m_dump_nsstring_measurement.Write(array);
-        m_dump_nsarray_measurement.Write(array);
-        m_dump_nsdictionary_measurement.Write(array);
-        m_dump_nsset_measurement.Write(array);
-        m_dump_nsbundle_measurement.Write(array);
-        m_dump_nsdate_measurement.Write(array);
-
-        CFDataRef xmlData = CFPropertyListCreateData(kCFAllocatorDefault, array.get(), kCFPropertyListXMLFormat_v1_0, 0, NULL);
-        
-        CFURLRef file = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)m_out_path.c_str(), m_out_path.size(), FALSE);
-        
-        CFURLWriteDataAndPropertiesToResource(file,xmlData,NULL,NULL);
+        m_dump_std_vector_measurement.WriteAverageValue(results);
+        m_dump_std_list_measurement.WriteAverageValue(results);
+        m_dump_std_map_measurement.WriteAverageValue(results);
+        m_dump_std_string_measurement.WriteAverageValue(results);
+        
+        m_dump_nsstring_measurement.WriteAverageValue(results);
+        m_dump_nsarray_measurement.WriteAverageValue(results);
+        m_dump_nsdictionary_measurement.WriteAverageValue(results);
+        m_dump_nsset_measurement.WriteAverageValue(results);
+        m_dump_nsbundle_measurement.WriteAverageValue(results);
+        m_dump_nsdate_measurement.WriteAverageValue(results);
+        results.Write(m_out_path.c_str());
     }
     
 private:
index 65b601e..8ceec65 100644 (file)
@@ -179,21 +179,15 @@ public:
         }
     }
     
-    void
-    Results ()
+    virtual void
+    WriteResults (Results &results)
     {
-        CFCMutableArray array;
-        m_fetch_frames_measurement.Write(array);
-        m_file_line_bp_measurement.Write(array);
-        m_fetch_modules_measurement.Write(array);
-        m_fetch_vars_measurement.Write(array);
-        m_run_expr_measurement.Write(array);
-
-        CFDataRef xmlData = CFPropertyListCreateData(kCFAllocatorDefault, array.get(), kCFPropertyListXMLFormat_v1_0, 0, NULL);
-        
-        CFURLRef file = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)m_out_path.c_str(), m_out_path.size(), FALSE);
-        
-        CFURLWriteDataAndPropertiesToResource(file,xmlData,NULL,NULL);
+        m_fetch_frames_measurement.WriteAverageValue(results);
+        m_file_line_bp_measurement.WriteAverageValue(results);
+        m_fetch_modules_measurement.WriteAverageValue(results);
+        m_fetch_vars_measurement.WriteAverageValue(results);
+        m_run_expr_measurement.WriteAverageValue(results);
+        results.Write(m_out_path.c_str());
     }
     
 private:
diff --git a/lldb/tools/lldb-perf/lib/Gauge.cpp b/lldb/tools/lldb-perf/lib/Gauge.cpp
new file mode 100644 (file)
index 0000000..7e414a4
--- /dev/null
@@ -0,0 +1,52 @@
+//===-- Gauge.cpp -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Gauge.h"
+
+template <>
+lldb_perf::Results::ResultSP
+lldb_perf::GetResult (const char *description, double value)
+{
+    if (description && description[0])
+    {
+        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
+        value_dict_ap->AddString("description", NULL, description);
+        value_dict_ap->AddDouble("value", NULL, value);
+        return Results::ResultSP (value_dict_ap.release());
+    }
+    return Results::ResultSP (new Results::Double (NULL, NULL, value));
+}
+
+template <>
+lldb_perf::Results::ResultSP
+lldb_perf::GetResult (const char *description, uint64_t value)
+{
+    if (description && description[0])
+    {
+        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
+        value_dict_ap->AddString("description", NULL, description);
+        value_dict_ap->AddUnsigned("value", NULL, value);
+        return Results::ResultSP (value_dict_ap.release());
+    }
+    return Results::ResultSP (new Results::Unsigned (NULL, NULL, value));
+}
+
+template <>
+lldb_perf::Results::ResultSP
+lldb_perf::GetResult (const char *description, std::string value)
+{
+    if (description && description[0])
+    {
+        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
+        value_dict_ap->AddString("description", NULL, description);
+        value_dict_ap->AddString("value", NULL, value.c_str());
+        return Results::ResultSP (value_dict_ap.release());
+    }
+    return Results::ResultSP (new Results::String (NULL, NULL, value.c_str()));
+}
index 60cfcd1..59d5d1f 100644 (file)
 #define PerfTestDriver_Gauge_h
 
 #include <functional>
+#include <string>
+
+#include "Results.h"
+
+class CFCMutableDictionary;
 
 namespace lldb_perf {
 
-template <class TASizeType>
+template <class T>
 class Gauge
 {
 public:
-    typedef TASizeType SizeType;
-public:
+    typedef T ValueType;
+
     Gauge ()
     {}
     
@@ -30,22 +35,32 @@ public:
     virtual void
     Start () = 0;
     
-    virtual SizeType
+    virtual ValueType
     Stop () = 0;
-    
-    virtual  SizeType
-    GetValue () = 0;
-    
-    template <typename F, typename... Args>
-    SizeType
-    Measure (F f,Args... args)
-    {
-        Start();
-        f(args...);
-        return Stop();
-    }
+
+    virtual ValueType
+    GetStartValue () const = 0;
+
+    virtual ValueType
+    GetStopValue () const = 0;
+
+    virtual ValueType
+    GetDeltaValue () const = 0;
 
 };
+
+template <class T>
+Results::ResultSP GetResult (const char *description, T value);
+
+template <>
+Results::ResultSP GetResult (const char *description, double value);
+
+template <>
+Results::ResultSP GetResult (const char *description, uint64_t value);
+
+template <>
+Results::ResultSP GetResult (const char *description, std::string value);
+
 }
 
 #endif
index 77e6943..eaea82f 100644 (file)
 
 namespace lldb_perf
 {
-template <typename GaugeType, typename Action>
-class Measurement : public WriteToPList
+template <typename GaugeType, typename Callable>
+class Measurement : public WriteResults
 {
 public:
     Measurement () :
         m_gauge (),
-        m_action (),
+        m_callable (),
         m_metric ()
     {
     }
     
-    Measurement (Action act, const char* name = NULL, const char* desc = NULL)  :
+    Measurement (Callable callable, const char* name, const char* desc)  :
         m_gauge (),
-        m_action (act),
-        m_metric (Metric<typename GaugeType::SizeType>(name, desc))
+        m_callable (callable),
+        m_metric (Metric<typename GaugeType::ValueType>(name, desc))
     {
     }
-    
-    template <typename GaugeType_Rhs, typename Action_Rhs>
-    Measurement (const Measurement<GaugeType_Rhs, Action_Rhs>& rhs) :
+
+    Measurement (const char* name, const char* desc)  :
+        m_gauge (),
+        m_callable (),
+        m_metric (Metric<typename GaugeType::ValueType>(name, desc))
+    {
+    }
+
+    template <typename GaugeType_Rhs, typename Callable_Rhs>
+    Measurement (const Measurement<GaugeType_Rhs, Callable_Rhs>& rhs) :
         m_gauge(rhs.GetGauge()),
-        m_action(rhs.GetAction()),
+        m_callable(rhs.GetCallable()),
         m_metric(rhs.GetMetric())
     {
     }
@@ -47,13 +54,15 @@ public:
     void
     operator () (Args... args)
     {
-        m_metric.Append (m_gauge.Measure(m_action, args...));
+        m_gauge.Start();
+        m_callable(args...);
+        m_metric.Append (m_gauge.Stop());
     }
     
-    virtual const Action&
-    GetAction () const
+    virtual const Callable&
+    GetCallable () const
     {
-        return m_action;
+        return m_callable;
     }
     
     virtual const GaugeType&
@@ -62,7 +71,7 @@ public:
         return m_gauge;
     }
     
-    virtual const Metric<typename GaugeType::SizeType>&
+    virtual const Metric<typename GaugeType::ValueType>&
     GetMetric () const
     {
         return m_metric;
@@ -74,7 +83,7 @@ public:
         m_gauge.Start();
     }
     
-    typename GaugeType::SizeType
+    typename GaugeType::ValueType
     Stop ()
     {
         auto value = m_gauge.Stop();
@@ -83,42 +92,63 @@ public:
     }
         
     virtual void
-    Write (CFCMutableArray& parent)
+    Write (CFCMutableDictionary& parent)
     {
         m_metric.Write(parent);
     }
 
+    void
+    WriteStartValue (Results &results)
+    {
+        auto metric = GetMetric ();
+        results.GetDictionary().Add(metric.GetName(), metric.GetDescription(), lldb_perf::GetResult<typename GaugeType::ValueType> (NULL, metric.GetStartValue()));
+    }
+    
+    void
+    WriteStopValue (Results &results)
+    {
+        auto metric = GetMetric ();
+        results.GetDictionary().Add(metric.GetName(), metric.GetDescription(), lldb_perf::GetResult<typename GaugeType::ValueType> (NULL, metric.GetStopValue()));
+    }
+
+    void
+    WriteAverageValue (Results &results)
+    {
+        auto metric = GetMetric ();
+        results.GetDictionary().Add(metric.GetName(), metric.GetDescription(), lldb_perf::GetResult<typename GaugeType::ValueType> (NULL, metric.GetAverage()));
+    }
+
 protected:
     GaugeType m_gauge;
-    Action m_action;
-    Metric<typename GaugeType::SizeType> m_metric;
+    Callable m_callable;
+    Metric<typename GaugeType::ValueType> m_metric;
 };
     
-template <typename Action>
-class TimeMeasurement : public Measurement<TimeGauge,Action>
+template <typename Callable>
+class TimeMeasurement : public Measurement<TimeGauge,Callable>
 {
 public:
     TimeMeasurement () :
-        Measurement<TimeGauge,Action> ()
+        Measurement<TimeGauge,Callable> ()
     {
     }
     
-    TimeMeasurement (Action act,
+    TimeMeasurement (Callable callable,
                      const char* name = NULL,
                      const char* descr = NULL) :
-        Measurement<TimeGauge,Action> (act, name, descr)
+        Measurement<TimeGauge,Callable> (callable, name, descr)
     {
     }
     
-    template <typename Action_Rhs>
-    TimeMeasurement (const TimeMeasurement<Action_Rhs>& rhs) :
-        Measurement<TimeGauge,Action>(rhs)
+    template <typename Callable_Rhs>
+    TimeMeasurement (const TimeMeasurement<Callable_Rhs>& rhs) :
+        Measurement<TimeGauge,Callable>(rhs)
     {
     }
     
-    template <typename GaugeType_Rhs, typename Action_Rhs>
-    TimeMeasurement (const Measurement<GaugeType_Rhs, Action_Rhs>& rhs) :
-        Measurement<GaugeType_Rhs,Action_Rhs>(rhs)
+    template <typename GaugeType_Rhs, typename Callable_Rhs>
+    TimeMeasurement (const Measurement<GaugeType_Rhs, Callable_Rhs>& rhs) :
+        Measurement<GaugeType_Rhs,Callable_Rhs>(rhs)
     {
     }
     
@@ -126,29 +156,39 @@ public:
     void
     operator () (Args... args)
     {
-        Measurement<TimeGauge,Action>::operator()(args...);
+        Measurement<TimeGauge,Callable>::operator()(args...);
     }
 };
 
-template <typename Action>
-class MemoryMeasurement : public Measurement<MemoryGauge,Action>
+template <typename Callable>
+class MemoryMeasurement : public Measurement<MemoryGauge,Callable>
 {
 public:
-    MemoryMeasurement () : Measurement<MemoryGauge,Action> ()
+    MemoryMeasurement () : Measurement<MemoryGauge,Callable> ()
     {
     }
     
-    MemoryMeasurement (Action act, const char* name = NULL, const char* descr = NULL) : Measurement<MemoryGauge,Action> (act, name, descr)
+    MemoryMeasurement (Callable callable,
+                       const char* name,
+                       const char* descr) :
+        Measurement<MemoryGauge,Callable> (callable, name, descr)
     {
     }
-    
-    template <typename Action_Rhs>
-    MemoryMeasurement (const MemoryMeasurement<Action_Rhs>& rhs) : Measurement<MemoryGauge,Action>(rhs)
+
+    MemoryMeasurement (const char* name, const char* descr) :
+        Measurement<MemoryGauge,Callable> (name, descr)
+    {
+    }
+
+    template <typename Callable_Rhs>
+    MemoryMeasurement (const MemoryMeasurement<Callable_Rhs>& rhs) :
+        Measurement<MemoryGauge,Callable>(rhs)
     {
     }
     
-    template <typename GaugeType_Rhs, typename Action_Rhs>
-    MemoryMeasurement (const Measurement<GaugeType_Rhs, Action_Rhs>& rhs) : Measurement<GaugeType_Rhs,Action_Rhs>(rhs)
+    template <typename GaugeType_Rhs, typename Callable_Rhs>
+    MemoryMeasurement (const Measurement<GaugeType_Rhs, Callable_Rhs>& rhs) :
+        Measurement<GaugeType_Rhs,Callable_Rhs>(rhs)
     {
     }
     
@@ -156,7 +196,7 @@ public:
     void
     operator () (Args... args)
     {
-        Measurement<MemoryGauge,Action>::operator()(args...);
+        Measurement<MemoryGauge,Callable>::operator()(args...);
     }
 };
     
index 30b587d..a53b0ac 100644 (file)
@@ -70,7 +70,16 @@ MemoryStats::operator / (size_t n)
     return *this;
 }
 
-MemoryGauge::SizeType
+Results::ResultSP
+MemoryStats::GetResult (const char *name, const char *description) const
+{
+    std::unique_ptr<Results::Dictionary> dict_ap (new Results::Dictionary (name, NULL));
+    dict_ap->AddUnsigned("resident", NULL, GetResidentSize());
+    dict_ap->AddUnsigned("max_resident", NULL, GetMaxResidentSize());
+    return Results::ResultSP(dict_ap.release());
+}
+
+MemoryGauge::ValueType
 MemoryGauge::Now ()
 {
     task_t task = mach_task_self();
@@ -84,8 +93,9 @@ MemoryGauge::Now ()
 }
 
 MemoryGauge::MemoryGauge () :
+    m_state(MemoryGauge::State::eNeverUsed),
     m_start(),
-    m_state(MemoryGauge::State::eNeverUsed)
+    m_delta()
 {
 }
 
@@ -96,18 +106,27 @@ MemoryGauge::Start ()
        m_start = Now();
 }
 
-MemoryGauge::SizeType
+MemoryGauge::ValueType
 MemoryGauge::Stop ()
 {
-       auto stop = Now();
+       m_stop = Now();
        assert(m_state == MemoryGauge::State::eCounting && "cannot stop a non-started gauge");
        m_state = MemoryGauge::State::eStopped;
-       return (m_value = stop-m_start);
+    m_delta = m_stop - m_start;
+       return m_delta;
 }
 
-MemoryGauge::SizeType
-MemoryGauge::GetValue ()
+
+MemoryGauge::ValueType
+MemoryGauge::GetDeltaValue () const
 {
        assert(m_state == MemoryGauge::State::eStopped && "gauge must be used before you can evaluate it");
-       return m_value;
+       return m_delta;
+}
+
+template <>
+Results::ResultSP
+lldb_perf::GetResult (const char *description, MemoryStats value)
+{
+    return value.GetResult (NULL, description);
 }
index 1781def..53f46bb 100644 (file)
 #define __PerfTestDriver__MemoryGauge__
 
 #include "Gauge.h"
+#include "Results.h"
 
 #include <mach/task_info.h>
 
-namespace lldb_perf
-{
+namespace lldb_perf {
+
 class MemoryStats
 {
 public:
@@ -37,19 +38,19 @@ public:
     operator / (size_t rhs);
     
     mach_vm_size_t
-    GetVirtualSize ()
+    GetVirtualSize () const
     {
         return m_virtual_size;
     }
     
     mach_vm_size_t
-    GetResidentSize ()
+    GetResidentSize () const
     {
         return m_resident_size;
     }
     
     mach_vm_size_t
-    GetMaxResidentSize ()
+    GetMaxResidentSize () const
     {
         return m_max_resident_size;
     }
@@ -72,6 +73,8 @@ public:
         m_max_resident_size = mrs;
     }
     
+    Results::ResultSP
+    GetResult (const char *name, const char *description) const;
 private:
     mach_vm_size_t m_virtual_size;
     mach_vm_size_t m_resident_size;
@@ -91,11 +94,23 @@ public:
     void
     Start ();
     
-    SizeType
+    ValueType
     Stop ();
     
-    SizeType
-    GetValue ();
+    virtual ValueType
+    GetStartValue() const
+    {
+        return m_start;
+    }
+
+    virtual ValueType
+    GetStopValue() const
+    {
+        return m_stop;
+    }
+
+    virtual ValueType
+    GetDeltaValue() const;
 
 private:
     enum class State
@@ -105,14 +120,19 @@ private:
         eStopped
     };
     
-    SizeType
+    ValueType
     Now ();
     
-    SizeType m_start;
     State m_state;
-    SizeType m_value;
-    
+    ValueType m_start;
+    ValueType m_stop;
+    ValueType m_delta;
 };
-}
 
-#endif /* defined(__PerfTestDriver__MemoryGauge__) */
+template <>
+Results::ResultSP
+GetResult (const char *description, MemoryStats value);
+    
+} // namespace lldb_perf
+
+#endif // #ifndef __PerfTestDriver__MemoryGauge__
index 5f17bea..bf8120f 100644 (file)
@@ -18,14 +18,16 @@ using namespace lldb_perf;
 
 template <class T>
 Metric<T>::Metric () : Metric ("")
-{}
+{
+}
 
 template <class T>
 Metric<T>::Metric (const char* n, const char* d) :
-m_name(n ? n : ""),
-m_description(d ? d : ""),
-m_dataset ()
-{}
+    m_name(n ? n : ""),
+    m_description(d ? d : ""),
+    m_dataset ()
+{
+}
 
 template <class T>
 void
@@ -59,32 +61,32 @@ Metric<T>::GetAverage () const
 }
 
 template <>
-void Metric<double>::WriteImpl (CFCMutableArray& parent, identity<double>)
+void Metric<double>::WriteImpl (CFCMutableDictionary& parent_dict, const char *name, const char *description, double value)
 {
+    assert(name && name[0]);
     CFCMutableDictionary dict;
-    dict.AddValueCString(CFCString("name").get(), GetName(), true);
-    dict.AddValueCString(CFCString("description").get(),GetDescription(), true);
-    dict.AddValueDouble(CFCString("value").get(),this->GetAverage(), true);
-    parent.AppendValue(dict.get(), true);
+    if (description && description[0])
+        dict.AddValueCString(CFCString("description").get(),description, true);
+    dict.AddValueDouble(CFCString("value").get(),value, true);
+    parent_dict.AddValue(CFCString(name).get(), dict.get(), true);
 }
 
 template <>
-void Metric<MemoryStats>::WriteImpl (CFCMutableArray& parent, identity<MemoryStats>)
+void Metric<MemoryStats>::WriteImpl (CFCMutableDictionary& parent_dict, const char *name, const char *description, MemoryStats value)
 {
     CFCMutableDictionary dict;
-    dict.AddValueCString(CFCString("name").get(), GetName(), true);
-    dict.AddValueCString(CFCString("description").get(), GetDescription(), true);
-    CFCMutableDictionary value;
-
-    auto avg = this->GetAverage();
-    
-    value.AddValueUInt64(CFCString("virtual").get(), avg.GetVirtualSize(), true);
-    value.AddValueUInt64(CFCString("resident").get(), avg.GetResidentSize(), true);
-    value.AddValueUInt64(CFCString("max_resident").get(), avg.GetMaxResidentSize(), true);
+    if (description && description[0])
+        dict.AddValueCString(CFCString("description").get(),description, true);
+    CFCMutableDictionary value_dict;
+    // don't write out the "virtual size", it doesn't mean anything useful as it includes
+    // all of the shared cache and many other things that make it way too big to be useful
+    //value_dict.AddValueUInt64(CFCString("virtual").get(), value.GetVirtualSize(), true);
+    value_dict.AddValueUInt64(CFCString("resident").get(), value.GetResidentSize(), true);
+    value_dict.AddValueUInt64(CFCString("max_resident").get(), value.GetMaxResidentSize(), true);
     
-    dict.AddValue(CFCString("value").get(), value.get(), true);
-    
-    parent.AppendValue(dict.get(), true);
+    dict.AddValue(CFCString("value").get(),value_dict.get(), true);
+
+    parent_dict.AddValue(CFCString(name).get(), dict.get(), true);
 }
 
 template class lldb_perf::Metric<double>;
index 0e65d82..bdbe824 100644 (file)
 #include <string>
 #include <mach/task_info.h>
 
-#include "CFCMutableArray.h"
+#include "CFCMutableDictionary.h"
 
 namespace lldb_perf {
 
 class MemoryStats;
 
-class WriteToPList
+class WriteResults
 {
 public:
     virtual void
-    Write (CFCMutableArray& parent) = 0;
+    Write (CFCMutableDictionary& parent) = 0;
     
     virtual
-    ~WriteToPList () {}
+    ~WriteResults () {}
 };
 
 template <class ValueType>
-class Metric : public WriteToPList
+class Metric : public WriteResults
 {
 public:
     Metric ();
@@ -50,32 +50,31 @@ public:
     GetSum () const;
     
     const char*
-    GetName ()
+    GetName () const
     {
+        if (m_name.empty())
+            return NULL;
         return m_name.c_str();
     }
 
     const char*
-    GetDescription ()
+    GetDescription () const
     {
+        if (m_description.empty())
+            return NULL;
         return m_description.c_str();
     }
     
     virtual void
-    Write (CFCMutableArray& parent)
+    Write (CFCMutableDictionary& parent)
     {
-        WriteImpl(parent, identity<ValueType>());
+        WriteImpl(parent, GetName(), GetDescription(), GetAverage());
     }
-    
-private:
 
-    template<typename T>
-    struct identity { typedef T type; };
-    
-    void WriteImpl (CFCMutableArray& parent, identity<double>);
+    static void WriteImpl (CFCMutableDictionary& parent, const char *name, const char *description, double);
+    static void WriteImpl (CFCMutableDictionary& parent, const char *name, const char *description, MemoryStats);
 
-    void WriteImpl (CFCMutableArray& parent, identity<MemoryStats>);
-    
+private:
     std::string m_name;
     std::string m_description;
     std::vector<ValueType> m_dataset;
diff --git a/lldb/tools/lldb-perf/lib/Results.cpp b/lldb/tools/lldb-perf/lib/Results.cpp
new file mode 100644 (file)
index 0000000..de86f6b
--- /dev/null
@@ -0,0 +1,267 @@
+//===-- Results.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Results.h"
+#include <assert.h>
+
+#ifdef __APPLE__
+#include "CFCMutableArray.h"
+#include "CFCMutableDictionary.h"
+#include "CFCReleaser.h"
+#include "CFCString.h"
+#endif
+
+using namespace lldb_perf;
+
+static void
+AddResultToArray (CFCMutableArray &array, Results::Result *result);
+
+static void
+AddResultToDictionary (CFCMutableDictionary &parent_dict, const char *key, Results::Result *result);
+
+static void
+AddResultToArray (CFCMutableArray &parent_array, Results::Result *result)
+{
+    switch (result->GetType())
+    {
+    case Results::Result::Type::Invalid:
+        break;
+            
+    case Results::Result::Type::Array:
+        {
+            Results::Array *value = result->GetAsArray();
+            CFCMutableArray array;
+            value->ForEach([&array](const Results::ResultSP &value_sp) -> bool
+                           {
+                               AddResultToArray (array, value_sp.get());
+                               return true;
+                           });
+            parent_array.AppendValue(array.get(), true);
+        }
+        break;
+
+    case Results::Result::Type::Dictionary:
+        {
+            Results::Dictionary *value = result->GetAsDictionary();
+            CFCMutableDictionary dict;
+            value->ForEach([&dict](const std::string &key, const Results::ResultSP &value_sp) -> bool
+                           {
+                               AddResultToDictionary (dict, key.c_str(), value_sp.get());
+                               return true;
+                           });
+            if (result->GetDescription())
+            {
+                dict.AddValueCString(CFSTR("description"), result->GetDescription());
+            }
+            parent_array.AppendValue(dict.get(), true);
+        }
+        break;
+    
+    case Results::Result::Type::Double:
+        {
+            double d = result->GetAsDouble()->GetValue();
+            CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &d));
+            if (cf_number.get())
+                parent_array.AppendValue(cf_number.get(), true);
+        }
+        break;
+    case Results::Result::Type::String:
+        {
+            CFCString cfstr (result->GetAsString()->GetValue());
+            if (cfstr.get())
+                parent_array.AppendValue(cfstr.get(), true);
+        }
+        break;
+            
+    case Results::Result::Type::Unsigned:
+        {
+            uint64_t uval64 = result->GetAsUnsigned()->GetValue();
+            CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &uval64));
+            if (cf_number.get())
+                parent_array.AppendValue(cf_number.get(), true);
+        }
+        break;
+
+    default:
+        assert (!"unhandled result");
+        break;
+    }
+}
+
+
+static void
+AddResultToDictionary (CFCMutableDictionary &parent_dict, const char *key, Results::Result *result)
+{
+    assert (key && key[0]);
+    CFCString cf_key(key);
+    switch (result->GetType())
+    {
+    case Results::Result::Type::Invalid:
+        break;
+    
+    case Results::Result::Type::Array:
+        {
+            Results::Array *value = result->GetAsArray();
+            CFCMutableArray array;
+            value->ForEach([&array](const Results::ResultSP &value_sp) -> bool
+                           {
+                               AddResultToArray (array, value_sp.get());
+                               return true;
+                           });
+            parent_dict.AddValue(cf_key.get(), array.get(), true);
+        }
+        break;
+    case Results::Result::Type::Dictionary:
+        {
+            Results::Dictionary *value = result->GetAsDictionary();
+            CFCMutableDictionary dict;
+            value->ForEach([&dict](const std::string &key, const Results::ResultSP &value_sp) -> bool
+                           {
+                               AddResultToDictionary (dict, key.c_str(), value_sp.get());
+                               return true;
+                           });
+            if (result->GetDescription())
+            {
+                dict.AddValueCString(CFSTR("description"), result->GetDescription());
+            }
+            parent_dict.AddValue(cf_key.get(), dict.get(), true);
+        }
+        break;
+    case Results::Result::Type::Double:
+        {
+            parent_dict.SetValueDouble(cf_key.get(), result->GetAsDouble()->GetValue(), true);
+        }
+        break;
+    case Results::Result::Type::String:
+        {
+            parent_dict.SetValueCString(cf_key.get(), result->GetAsString()->GetValue(), true);
+        }
+        break;
+
+    case Results::Result::Type::Unsigned:
+        {
+            parent_dict.SetValueUInt64 (cf_key.get(), result->GetAsUnsigned()->GetValue(), true);
+        }
+        break;
+    default:
+        assert (!"unhandled result");
+        break;
+    }
+}
+void
+Results::Write (const char *out_path)
+{
+#ifdef __APPLE__
+    CFCMutableDictionary dict;
+    
+    m_results.ForEach([&dict](const std::string &key, const ResultSP &value_sp) -> bool
+                      {
+                          AddResultToDictionary (dict, key.c_str(), value_sp.get());
+                          return true;
+                      });
+    CFDataRef xmlData = CFPropertyListCreateData(kCFAllocatorDefault, dict.get(), kCFPropertyListXMLFormat_v1_0, 0, NULL);
+    
+    CFURLRef file = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)out_path, strlen(out_path), FALSE);
+    
+    CFURLWriteDataAndPropertiesToResource(file, xmlData, NULL, NULL);
+#endif
+}
+
+void
+Results::Dictionary::AddUnsigned (const char *name, const char *description, uint64_t value)
+{
+    assert (name && name[0]);
+    if (description && description[0])
+    {
+        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
+        value_dict_ap->AddString("description", NULL, description);
+        value_dict_ap->AddUnsigned("value", NULL, value);
+        m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
+    }
+    else
+        m_dictionary[std::string(name)] = ResultSP (new Unsigned (name, description, value));
+}
+
+void
+Results::Dictionary::AddDouble (const char *name, const char *description, double value)
+{
+    assert (name && name[0]);
+    
+    if (description && description[0])
+    {
+        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
+        value_dict_ap->AddString("description", NULL, description);
+        value_dict_ap->AddDouble("value", NULL, value);
+        m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
+    }
+    else
+        m_dictionary[std::string(name)] = ResultSP (new Double (name, description, value));
+}
+void
+Results::Dictionary::AddString (const char *name, const char *description, const char *value)
+{
+    assert (name && name[0]);
+    if (description && description[0])
+    {
+        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
+        value_dict_ap->AddString("description", NULL, description);
+        value_dict_ap->AddString("value", NULL, value);
+        m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
+    }
+    else
+        m_dictionary[std::string(name)] = ResultSP (new String (name, description, value));
+}
+
+void
+Results::Dictionary::Add (const char *name, const char *description, const ResultSP &result_sp)
+{
+    assert (name && name[0]);
+    if (description && description[0])
+    {
+        std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ());
+        value_dict_ap->AddString("description", NULL, description);
+        value_dict_ap->Add("value", NULL, result_sp);
+        m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release());
+    }
+    else
+        m_dictionary[std::string(name)] = result_sp;
+}
+
+void
+Results::Dictionary::ForEach (const std::function <bool (const std::string &, const ResultSP &)> &callback)
+{
+    collection::const_iterator pos, end = m_dictionary.end();
+    for (pos = m_dictionary.begin(); pos != end; ++pos)
+    {
+        if (callback (pos->first.c_str(), pos->second) == false)
+            return;
+    }
+}
+
+
+
+void
+Results::Array::Append (const ResultSP &result_sp)
+{
+    m_array.push_back (result_sp);
+}
+
+void
+Results::Array::ForEach (const std::function <bool (const ResultSP &)> &callback)
+{
+    collection::const_iterator pos, end = m_array.end();
+    for (pos = m_array.begin(); pos != end; ++pos)
+    {
+        if (callback (*pos) == false)
+            return;
+    }
+}
+
+
+
diff --git a/lldb/tools/lldb-perf/lib/Results.h b/lldb/tools/lldb-perf/lib/Results.h
new file mode 100644 (file)
index 0000000..f15b902
--- /dev/null
@@ -0,0 +1,312 @@
+//===-- Results.h -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __PerfTestDriver_Results_h__
+#define __PerfTestDriver_Results_h__
+
+#include <memory>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace lldb_perf {
+
+class Results
+{
+public:
+    class Array;
+    class Dictionary;
+    class Double;
+    class String;
+    class Unsigned;
+
+    class Result
+    {
+    public:
+        enum class Type
+        {
+            Invalid,
+            Array,
+            Dictionary,
+            Double,
+            String,
+            Unsigned
+        };
+
+        Result (Type type, const char *name, const char *description) :
+            m_name (),
+            m_description(),
+            m_type (type)
+        {
+            if (name && name[0])
+                m_name = name;
+            if (description && description[0])
+                m_description = description;
+        }
+
+        virtual
+        ~Result()
+        {
+        }
+
+        virtual void
+        Write (Results &results) = 0;
+
+        Array *
+        GetAsArray ()
+        {
+            if (m_type == Type::Array)
+                return (Array *)this;
+            return NULL;
+        }
+        Dictionary *
+        GetAsDictionary ()
+        {
+            if (m_type == Type::Dictionary)
+                return (Dictionary *)this;
+            return NULL;
+        }
+        Double *
+        GetAsDouble ()
+        {
+            if (m_type == Type::Double)
+                return (Double *)this;
+            return NULL;
+        }
+
+        String *
+        GetAsString ()
+        {
+            if (m_type == Type::String)
+                return (String *)this;
+            return NULL;
+        }
+        Unsigned *
+        GetAsUnsigned ()
+        {
+            if (m_type == Type::Unsigned)
+                return (Unsigned *)this;
+            return NULL;
+        }
+        
+        const char *
+        GetName() const
+        {
+            if (m_name.empty())
+                return NULL;
+            return m_name.c_str();
+        }
+
+        const char *
+        GetDescription() const
+        {
+            if (m_description.empty())
+                return NULL;
+            return m_description.c_str();
+        }
+
+        Type
+        GetType() const
+        {
+            return m_type;
+        }
+    
+    protected:
+        std::string m_name;
+        std::string m_description;
+        Type m_type;
+    };
+    
+    typedef std::shared_ptr<Result> ResultSP;
+
+    class Array : public Result
+    {
+    public:
+        Array (const char *name, const char *description) :
+            Result (Type::Array, name, description)
+        {
+        }
+        
+        virtual
+        ~Array()
+        {
+        }
+        
+        void
+        Append (const ResultSP &result_sp);
+
+        void
+        ForEach (const std::function <bool (const ResultSP &)> &callback);
+
+        virtual void
+        Write (Results &results)
+        {
+        }
+    protected:
+        typedef std::vector<ResultSP> collection;
+        collection m_array;
+    };
+
+    class Dictionary : public Result
+    {
+    public:
+        Dictionary () :
+            Result (Type::Dictionary, NULL, NULL)
+        {
+        }
+
+        Dictionary (const char *name, const char *description) :
+            Result (Type::Dictionary, name, description)
+        {
+        }
+
+        virtual
+        ~Dictionary()
+        {
+        }
+
+        virtual void
+        Write (Results &results)
+        {
+        }
+
+        void
+        ForEach (const std::function <bool (const std::string &, const ResultSP &)> &callback);
+    
+        void
+        Add (const char *name, const char *description, const ResultSP &result_sp);
+        
+        void
+        AddDouble (const char *name, const char *descriptiorn, double value);
+        
+        void
+        AddUnsigned (const char *name, const char *description, uint64_t value);
+
+        void
+        AddString (const char *name, const char *description, const char *value);
+
+    protected:
+
+        typedef std::map<std::string, ResultSP> collection;
+        collection m_dictionary;
+    };
+    
+    class String : public Result
+    {
+    public:
+        String (const char *name, const char *description, const char *value) :
+            Result (Type::String, name, description),
+            m_string ()
+        {
+            if (value && value[0])
+                m_string = value;
+        }
+
+        virtual
+        ~String()
+        {
+        }
+
+        virtual void
+        Write (Results &results)
+        {
+        }
+
+        const char *
+        GetValue () const
+        {
+            return m_string.empty() ? NULL : m_string.c_str();
+        }
+        
+    protected:
+        std::string m_string;
+    };
+
+    class Double : public Result
+    {
+    public:
+        Double (const char *name, const char *description, double value) :
+            Result (Type::Double, name, description),
+            m_double (value)
+        {
+        }
+        
+        virtual
+        ~Double()
+        {
+        }
+        
+        virtual void
+        Write (Results &results)
+        {
+        }
+        
+        double
+        GetValue () const
+        {
+            return m_double;
+        }
+        
+    protected:
+        double m_double;
+    };
+
+    class Unsigned : public Result
+    {
+    public:
+        Unsigned (const char *name, const char *description, uint64_t value) :
+            Result (Type::Unsigned, name, description),
+            m_unsigned (value)
+        {
+        }
+        
+        virtual
+        ~Unsigned()
+        {
+        }
+
+        virtual void
+        Write (Results &results)
+        {
+        }
+        
+        uint64_t
+        GetValue () const
+        {
+            return m_unsigned;
+        }
+
+    protected:
+        uint64_t m_unsigned;
+    };
+
+    Results () :
+        m_results ()
+    {
+    }
+    
+    ~Results()
+    {
+    }
+    
+    Dictionary &
+    GetDictionary ()
+    {
+        return m_results;
+    }
+
+    void
+    Write (const char *path);
+    
+protected:
+    Dictionary m_results;
+};
+    
+} // namespace lldb_perf
+#endif // #ifndef __PerfTestDriver_Results_h__
index 4f5c00c..7a7c48a 100644 (file)
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "TestCase.h"
+#include "Results.h"
 #include "Xcode.h"
 
 using namespace lldb_perf;
@@ -63,134 +64,167 @@ TestCase::GetVerbose ()
 void
 TestCase::Loop ()
 {
-       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;
-                bool selected_thread = 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));
-                    bool select_thread = false;
-                                       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:
-                            select_thread = true;
-                            if (m_verbose) printf("trace\n");
-                            break;
-                            
-                                       case eStopReasonPlanComplete:
-                            select_thread = true;
-                            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:
-                            select_thread = true;
-                            if (m_verbose) printf("exception\n");
-                            fatal = true;
-                            break;
-                                       case eStopReasonBreakpoint:
-                            select_thread = true;
-                            if (m_verbose) printf("breakpoint id = %lld.%lld\n",thread.GetStopReasonDataAtIndex(0),thread.GetStopReasonDataAtIndex(1));
-                            break;
-                                       case eStopReasonWatchpoint:
-                            select_thread = true;
-                            if (m_verbose) printf("watchpoint id = %lld\n",thread.GetStopReasonDataAtIndex(0));
-                            break;
-                                       case eStopReasonSignal:
-                            select_thread = true;
-                            if (m_verbose) printf("signal %d\n",(int)thread.GetStopReasonDataAtIndex(0));
-                            break;
-                                       }
-                    if (select_thread && !selected_thread)
+        bool call_test_step = false;
+        if (m_process.IsValid())
+        {
+            SBEvent evt;
+            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:
+                {
+                    call_test_step = true;
+                    bool fatal = false;
+                    bool selected_thread = false;
+                    for (auto thread_index = 0; thread_index < m_process.GetNumThreads(); thread_index++)
                     {
-                        m_thread = thread;
-                        selected_thread = m_process.SetSelectedThread(thread);
-                    }
-                               }
-                               if (fatal)
-                               {
-                                       if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
-                                       exit(1);
-                               }
-                               if (m_verbose)
-                                       printf("RUNNING STEP %d\n",m_step);
-                ActionWanted action;
-                               TestStep(m_step, action);
-                               m_step++;
-                SBError err;
-                               switch (action.type)
-                               {
-                                       case ActionWanted::Type::eContinue:
-                        err = m_process.Continue();
-                                               break;
-                    case ActionWanted::Type::eStepOut:
-                        if (action.thread.IsValid() == false)
+                        SBThread thread(m_process.GetThreadAtIndex(thread_index));
+                        SBFrame frame(thread.GetFrameAtIndex(0));
+                        bool select_thread = false;
+                        StopReason stop_reason = thread.GetStopReason();
+                        if (m_verbose) printf("tid = 0x%llx pc = 0x%llx ",thread.GetThreadID(),frame.GetPC());
+                        switch (stop_reason)
                         {
-                            if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
-                            if (m_verbose) printf("[finish invalid] I am gonna die at step %d\n",m_step);
-                            exit(501);
+                            case eStopReasonNone:
+                                if (m_verbose)
+                                    printf("none\n");
+                                break;
+                                
+                            case eStopReasonTrace:
+                                select_thread = true;
+                                if (m_verbose)
+                                    printf("trace\n");
+                                break;
+                                
+                            case eStopReasonPlanComplete:
+                                select_thread = true;
+                                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:
+                                select_thread = true;
+                                if (m_verbose)
+                                    printf("exception\n");
+                                fatal = true;
+                                break;
+                            case eStopReasonBreakpoint:
+                                select_thread = true;
+                                if (m_verbose)
+                                    printf("breakpoint id = %lld.%lld\n",thread.GetStopReasonDataAtIndex(0),thread.GetStopReasonDataAtIndex(1));
+                                break;
+                            case eStopReasonWatchpoint:
+                                select_thread = true;
+                                if (m_verbose)
+                                    printf("watchpoint id = %lld\n",thread.GetStopReasonDataAtIndex(0));
+                                break;
+                            case eStopReasonSignal:
+                                select_thread = true;
+                                if (m_verbose)
+                                    printf("signal %d\n",(int)thread.GetStopReasonDataAtIndex(0));
+                                break;
                         }
-                        m_process.SetSelectedThread(action.thread);
-                        action.thread.StepOut();
-                                               break;
-                                       case ActionWanted::Type::eNext:
-                        if (action.thread.IsValid() == false)
+                        if (select_thread && !selected_thread)
                         {
-                            if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
-                            if (m_verbose) printf("[next invalid] I am gonna die at step %d\n",m_step);
-                            exit(500);
+                            m_thread = thread;
+                            selected_thread = m_process.SetSelectedThread(thread);
                         }
-                        m_process.SetSelectedThread(action.thread);
-                        action.thread.StepOver();
-                                               break;
-                                       case ActionWanted::Type::eKill:
-                                               if (m_verbose) printf("I want to die\n");
-                                               m_process.Kill();
-                                               return;
-                               }
+                    }
+                    if (fatal)
+                    {
+                        if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
+                        exit(1);
+                    }
+                }
+                break;
                        }
                }
+        else
+        {
+            call_test_step = true;
+        }
+
+        if (call_test_step)
+        {
+            if (m_verbose)
+                printf("RUNNING STEP %d\n",m_step);
+            ActionWanted action;
+            TestStep(m_step, action);
+            m_step++;
+            SBError err;
+            switch (action.type)
+            {
+            case ActionWanted::Type::eContinue:
+                err = m_process.Continue();
+                break;
+            case ActionWanted::Type::eStepOut:
+                if (action.thread.IsValid() == false)
+                {
+                    if (m_verbose)
+                    {
+                        Xcode::RunCommand(m_debugger,"bt all",true);
+                        printf("error: invalid thread for step out on step %d\n", m_step);
+                    }
+                    exit(501);
+                }
+                m_process.SetSelectedThread(action.thread);
+                action.thread.StepOut();
+                break;
+            case ActionWanted::Type::eStepOver:
+                if (action.thread.IsValid() == false)
+                {
+                    if (m_verbose)
+                    {
+                        Xcode::RunCommand(m_debugger,"bt all",true);
+                        printf("error: invalid thread for step over %d\n",m_step);
+                    }
+                    exit(500);
+                }
+                m_process.SetSelectedThread(action.thread);
+                action.thread.StepOver();
+                break;
+            case ActionWanted::Type::eKill:
+                if (m_verbose)
+                    printf("kill\n");
+                m_process.Kill();
+                return;
+            }
+        }
+
        }
+    
        if (GetVerbose()) printf("I am gonna die at step %d\n",m_step);
 }
 
@@ -200,6 +234,8 @@ TestCase::Run (TestCase& test, int argc, const char** argv)
     if (test.Setup(argc, argv))
     {
         test.Loop();
-        test.Results();
+        Results results;
+        test.WriteResults(results);
     }
 }
+
index e20eeb6..cc376c8 100644 (file)
 #include "lldb/API/LLDB.h"
 #include "Measurement.h"
 
-namespace lldb_perf
-{
+namespace lldb_perf {
+
+class Results;
+    
 class TestCase
 {
 public:
@@ -24,7 +26,7 @@ public:
        {
                enum class Type
                {
-                       eNext,
+                       eStepOver,
                        eContinue,
             eStepOut,
                        eKill
@@ -47,7 +49,7 @@ public:
         void
         StepOver (lldb::SBThread t)
         {
-            type = Type::eNext;
+            type = Type::eStepOver;
             thread = t;
         }
 
@@ -90,7 +92,7 @@ public:
     GetVerbose ();
     
     virtual void
-    Results () = 0;
+    WriteResults (Results &results) = 0;
     
     template <typename G,typename A>
     Measurement<G,A> CreateMeasurement (A a, const char* name = NULL, const char* description = NULL)
index 428328b..52b6c29 100644 (file)
@@ -10,6 +10,9 @@
 #include "Timer.h"
 #include <assert.h>
 
+#include "CFCMutableDictionary.h"
+#include "CFCString.h"
+
 using namespace lldb_perf;
 
 TimeGauge::TimeType
@@ -19,7 +22,7 @@ TimeGauge::Now ()
 }
 
 TimeGauge::TimeGauge () :
-m_start(),
+    m_start(),
     m_state(TimeGauge::State::eNeverUsed)
 {
 }
@@ -34,15 +37,28 @@ TimeGauge::Start ()
 double
 TimeGauge::Stop ()
 {
-       auto stop = Now();
+       m_stop = Now();
        assert(m_state == TimeGauge::State::eCounting && "cannot stop a non-started clock");
        m_state = TimeGauge::State::eStopped;
-       return (m_value = duration_cast<duration<double>>(stop-m_start).count());
+    m_delta = duration_cast<duration<double>>(m_stop-m_start).count();
+       return m_delta;
+}
+
+double
+TimeGauge::GetStartValue () const
+{
+    return (double)m_start.time_since_epoch().count() * (double)system_clock::period::num / (double)system_clock::period::den;
+}
+
+double
+TimeGauge::GetStopValue () const
+{
+    return (double)m_stop.time_since_epoch().count() * (double)system_clock::period::num / (double)system_clock::period::den;
 }
 
 double
-TimeGauge::GetValue ()
+TimeGauge::GetDeltaValue () const
 {
        assert(m_state == TimeGauge::State::eStopped && "clock must be used before you can evaluate it");
-       return m_value;
+       return m_delta;
 }
index 2f56e56..ff17935 100644 (file)
@@ -20,6 +20,29 @@ namespace lldb_perf
 {
 class TimeGauge : public Gauge<double>
 {
+public:
+    TimeGauge ();
+    
+    virtual
+    ~TimeGauge ()
+    {
+    }
+    
+    void
+    Start ();
+    
+    double
+    Stop ();
+    
+    virtual double
+    GetStartValue () const;
+    
+    virtual double
+    GetStopValue () const;
+
+    virtual double
+    GetDeltaValue () const;
+
 private:
     enum class State
     {
@@ -30,28 +53,13 @@ private:
     
     typedef high_resolution_clock::time_point TimeType;
     TimeType m_start;
-    double m_value;
+    TimeType m_stop;
+    double m_delta;
     State m_state;
     
     TimeType
     Now ();
     
-public:
-    TimeGauge ();
-    
-    virtual
-    ~TimeGauge ()
-    {
-    }
-    
-    void
-    Start ();
-    
-    double
-    Stop ();
-    
-    double
-    GetValue ();
 };
 }
 
index 6991229..0a9988b 100644 (file)
@@ -28,6 +28,9 @@
                26DBAD6316FA66DC008243D2 /* liblldbperf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1E373916F4035D00FF10BB /* liblldbperf.a */; };
                26DBAD6416FA66E0008243D2 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 264B3DE816F7E47600D1E7AB /* LLDB.framework */; };
                26DBAD6516FA66EA008243D2 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1E37DB16F7A03900FF10BB /* CoreFoundation.framework */; };
+               26DF762916FBCE7100B4CC2E /* Results.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DF762716FBCE7100B4CC2E /* Results.cpp */; };
+               26DF762A16FBCE7100B4CC2E /* Results.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DF762816FBCE7100B4CC2E /* Results.h */; };
+               26DF764316FBF30E00B4CC2E /* Gauge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DF764216FBF30E00B4CC2E /* Gauge.cpp */; };
                4C1E374E16F407C800FF10BB /* Gauge.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C1E374216F407C800FF10BB /* Gauge.h */; };
                4C1E374F16F407C800FF10BB /* Measurement.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C1E374316F407C800FF10BB /* Measurement.h */; };
                4C1E375016F407C800FF10BB /* MemoryGauge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E374416F407C800FF10BB /* MemoryGauge.cpp */; };
@@ -67,7 +70,6 @@
                4CE3707516FB703B00BFD501 /* liblldbperf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1E373916F4035D00FF10BB /* liblldbperf.a */; };
                4CE3707616FB704300BFD501 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 264B3DE816F7E47600D1E7AB /* LLDB.framework */; };
                4CE3707716FB704B00BFD501 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1E37DB16F7A03900FF10BB /* CoreFoundation.framework */; };
-               4CE3708816FB70EB00BFD501 /* stepping-testcase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE3708716FB70E100BFD501 /* stepping-testcase.cpp */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
                26DBAD4816FA637D008243D2 /* build-clang.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "build-clang.sh"; sourceTree = "<group>"; };
                26DBAD4916FA637D008243D2 /* lldb_perf_clang.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = lldb_perf_clang.cpp; sourceTree = "<group>"; };
                26DBAD5916FA63B1008243D2 /* lldb-perf-clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-perf-clang"; sourceTree = BUILT_PRODUCTS_DIR; };
+               26DF762716FBCE7100B4CC2E /* Results.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Results.cpp; sourceTree = "<group>"; };
+               26DF762816FBCE7100B4CC2E /* Results.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Results.h; sourceTree = "<group>"; };
+               26DF764216FBF30E00B4CC2E /* Gauge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Gauge.cpp; sourceTree = "<group>"; };
                4C1E373916F4035D00FF10BB /* liblldbperf.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = liblldbperf.a; sourceTree = BUILT_PRODUCTS_DIR; };
                4C1E374216F407C800FF10BB /* Gauge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Gauge.h; sourceTree = "<group>"; };
                4C1E374316F407C800FF10BB /* Measurement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Measurement.h; sourceTree = "<group>"; };
                4C86C5C416F7A36A00844407 /* LLDB.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LLDB.framework; path = build/Debug/LLDB.framework; sourceTree = "<group>"; };
                4C86C5C616F7A37800844407 /* LLDB.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LLDB.framework; path = build/Debug/LLDB.framework; sourceTree = "<group>"; };
                4C86C5D116F7CC8900844407 /* format-tester */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "format-tester"; sourceTree = BUILT_PRODUCTS_DIR; };
-               4CE3705416FB6FA100BFD501 /* lldb-step-test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-step-test"; sourceTree = BUILT_PRODUCTS_DIR; };
+               4CE3705416FB6FA100BFD501 /* lldb-perf-step */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-perf-step"; sourceTree = BUILT_PRODUCTS_DIR; };
                4CE3705616FB6FA100BFD501 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
                4CE3705816FB6FA100BFD501 /* lldb_step_test.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = lldb_step_test.1; sourceTree = "<group>"; };
                4CE3707216FB701000BFD501 /* lldb-perf-stepping.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-perf-stepping.cpp"; path = "stepping/lldb-perf-stepping.cpp"; sourceTree = "<group>"; };
                                4C1E37BA16F79E9D00FF10BB /* lldb-perf-formatters */,
                                4C86C5D116F7CC8900844407 /* format-tester */,
                                26DBAD5916FA63B1008243D2 /* lldb-perf-clang */,
-                               4CE3705416FB6FA100BFD501 /* lldb-step-test */,
+                               4CE3705416FB6FA100BFD501 /* lldb-perf-step */,
                                4CE3707C16FB70AD00BFD501 /* stepping-testcase */,
                        );
                        name = Products;
                        isa = PBXGroup;
                        children = (
                                4C1E374216F407C800FF10BB /* Gauge.h */,
+                               26DF764216FBF30E00B4CC2E /* Gauge.cpp */,
                                4C1E374316F407C800FF10BB /* Measurement.h */,
                                4C1E374416F407C800FF10BB /* MemoryGauge.cpp */,
                                4C1E374516F407C800FF10BB /* MemoryGauge.h */,
                                4C1E374616F407C800FF10BB /* Metric.cpp */,
                                4C1E374716F407C800FF10BB /* Metric.h */,
+                               26DF762716FBCE7100B4CC2E /* Results.cpp */,
+                               26DF762816FBCE7100B4CC2E /* Results.h */,
                                4C1E374816F407C800FF10BB /* TestCase.cpp */,
                                4C1E374916F407C800FF10BB /* TestCase.h */,
                                4C1E374A16F407C800FF10BB /* Timer.cpp */,
                        buildActionMask = 2147483647;
                        files = (
                                4C1E375716F407C800FF10BB /* Timer.h in Headers */,
+                               26DF762A16FBCE7100B4CC2E /* Results.h in Headers */,
                                4C1E378D16F40BB300FF10BB /* CFCMutableArray.h in Headers */,
                                4C1E374E16F407C800FF10BB /* Gauge.h in Headers */,
                                4C1E378716F40B9C00FF10BB /* CFCReleaser.h in Headers */,
                        );
                        name = "lldb-perf-step";
                        productName = "lldb-step-test";
-                       productReference = 4CE3705416FB6FA100BFD501 /* lldb-step-test */;
+                       productReference = 4CE3705416FB6FA100BFD501 /* lldb-perf-step */;
                        productType = "com.apple.product-type.tool";
                };
                4CE3707B16FB70AD00BFD501 /* stepping-testcase */ = {
                                4C1E375016F407C800FF10BB /* MemoryGauge.cpp in Sources */,
                                4C1E375416F407C800FF10BB /* TestCase.cpp in Sources */,
                                4C1E375816F407C800FF10BB /* Xcode.cpp in Sources */,
+                               26DF762916FBCE7100B4CC2E /* Results.cpp in Sources */,
                                4C1E375216F407C800FF10BB /* Metric.cpp in Sources */,
                                4C1E375616F407C800FF10BB /* Timer.cpp in Sources */,
                                4C1E378616F40B9600FF10BB /* CFCMutableSet.cpp in Sources */,
                                4C1E378516F40B9200FF10BB /* CFCMutableDictionary.cpp in Sources */,
                                4C1E378816F40B9F00FF10BB /* CFCString.cpp in Sources */,
+                               26DF764316FBF30E00B4CC2E /* Gauge.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               4CE3708816FB70EB00BFD501 /* stepping-testcase.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                        "$(inherited)",
                                        "$(SRCROOT)/../../build/Debug",
                                );
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                GCC_PREPROCESSOR_DEFINITIONS = (
                                        "DEBUG=1",
                                        "$(inherited)",
                                        "$(inherited)",
                                        "$(SRCROOT)/../../build/Debug",
                                );
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                OTHER_LDFLAGS = "-Wl,-rpath,@loader_path/../../../../build/Debug";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                SDKROOT = macosx;
                                        "$(inherited)",
                                        "$(SRCROOT)/../../build/Debug",
                                );
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                GCC_PREPROCESSOR_DEFINITIONS = (
                                        "DEBUG=1",
                                        "$(inherited)",
                                        "$(inherited)",
                                        "$(SRCROOT)/../../build/Debug",
                                );
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                OTHER_LDFLAGS = "-Wl,-rpath,@loader_path/../../../../build/Debug";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../include $(SRCROOT)/../../source/Host/macosx/cfcpp $(SRCROOT)/../";
                                        "$(inherited)",
                                        "$(SRCROOT)/../../build/Debug",
                                );
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                GCC_PREPROCESSOR_DEFINITIONS = (
                                        "DEBUG=1",
                                        "$(inherited)",
                                        "$(inherited)",
                                        "$(SRCROOT)/../../build/Debug",
                                );
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                OTHER_LDFLAGS = "-Wl,-rpath,@loader_path/../../../../build/Debug";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../ $(SRCROOT)/../../include/";
                4C86C5D816F7CC8900844407 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                GCC_PREPROCESSOR_DEFINITIONS = (
                                        "DEBUG=1",
                                        "$(inherited)",
                4C86C5D916F7CC8900844407 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                        };
                        name = Release;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                CLANG_ENABLE_MODULES = YES;
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                GCC_PREPROCESSOR_DEFINITIONS = (
                                        "DEBUG=1",
                                        "$(inherited)",
                                MACOSX_DEPLOYMENT_TARGET = 10.9;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                SDKROOT = macosx;
+                               USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../ $(SRCROOT)/../../include/";
                        };
                        name = Debug;
                };
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                CLANG_ENABLE_MODULES = YES;
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
                                MACOSX_DEPLOYMENT_TARGET = 10.9;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                SDKROOT = macosx;
+                               USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../ $(SRCROOT)/../../include/";
                        };
                        name = Release;
                };
                                4CE3705B16FB6FA100BFD501 /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
                };
                4CE3708216FB70AD00BFD501 /* Build configuration list for PBXNativeTarget "stepping-testcase" */ = {
                        isa = XCConfigurationList;
                                4CE3708416FB70AD00BFD501 /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
                };
 /* End XCConfigurationList section */
        };