Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r55083 - in trunk/libs/spirit/benchmarks: . qi
From: joel_at_[hidden]
Date: 2009-07-22 12:54:20


Author: djowel
Date: 2009-07-22 12:54:20 EDT (Wed, 22 Jul 2009)
New Revision: 55083
URL: http://svn.boost.org/trac/boost/changeset/55083

Log:
Updates to boilerplate benchmark code
Text files modified:
   trunk/libs/spirit/benchmarks/boiler_plate.cpp | 38 ++++--
   trunk/libs/spirit/benchmarks/measure.hpp | 77 ++++++++------
   trunk/libs/spirit/benchmarks/qi/uint_parser.cpp | 220 ++++-----------------------------------
   3 files changed, 93 insertions(+), 242 deletions(-)

Modified: trunk/libs/spirit/benchmarks/boiler_plate.cpp
==============================================================================
--- trunk/libs/spirit/benchmarks/boiler_plate.cpp (original)
+++ trunk/libs/spirit/benchmarks/boiler_plate.cpp 2009-07-22 12:54:20 EDT (Wed, 22 Jul 2009)
@@ -4,8 +4,11 @@
     Distributed under the Boost Software License, Version 1.0. (See accompanying
     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 ==============================================================================*/
+
+// determine the type of the live_code. we can use this to test the
+// result of the code we are benchmarking
+#define BOOST_SPIRIT_TEST_LIVE_CODE_TYPE long long
 #include "measure.hpp"
-#include <iostream>
 
 namespace
 {
@@ -13,12 +16,17 @@
     {
         typedef int type;
 
- void operator()(int x)
+ void benchmark(int x)
         {
- this->val ^= x; // here is where you put code that you want
+ this->val += x; // Here is where you put code that you want
                             // to benchmark. Make sure it returns something.
                             // Anything.
         }
+
+ static int initial()
+ {
+ return 1; // our initial value
+ }
 
         int val; // this is where the value is accumulated
     };
@@ -26,17 +34,15 @@
 
 int main()
 {
- int result;
- double base_time;
- int ret = test::run<f>(result, base_time, 100);
-
- std::cout
- << "f accumulated result: "
- << result
- << std::endl
- << "f time: "
- << base_time
- << std::endl;
-
- return ret;
+ BOOST_SPIRIT_TEST_BENCHMARK(
+ 1000000, // This is the maximum repetitions to execute
+ (f) // Place your tests here. For now, we have only one test: (f)
+ // If you have 3 tests a, b and c, this line will contain (a)(b)(c)
+ )
+
+ // This is ultimately responsible for preventing all the test code
+ // from being optimized away. Change this to return 0 and you
+ // unplug the whole test's life support system.
+ return test::live_code != 0;
 }
+

Modified: trunk/libs/spirit/benchmarks/measure.hpp
==============================================================================
--- trunk/libs/spirit/benchmarks/measure.hpp (original)
+++ trunk/libs/spirit/benchmarks/measure.hpp 2009-07-22 12:54:20 EDT (Wed, 22 Jul 2009)
@@ -2,6 +2,8 @@
 // 2005. Distributed under the Boost Software License, Version
 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
+#if !defined(BOOST_SPIRIT_TEST_BENCHMARK_HPP)
+#define BOOST_SPIRIT_TEST_BENCHMARK_HPP
 
 #ifdef _MSC_VER
 // inline aggressively
@@ -10,11 +12,14 @@
 # define _SECURE_SCL 0
 #endif
 
-#if !defined(LIVE_CODE_TYPE)
-# define LIVE_CODE_TYPE int
+#if !defined(BOOST_SPIRIT_TEST_LIVE_CODE_TYPE)
+# define BOOST_SPIRIT_TEST_LIVE_CODE_TYPE int
 #endif
 
 #include "high_resolution_timer.hpp"
+#include <iostream>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/preprocessor/stringize.hpp>
 
 namespace test
 {
@@ -22,12 +27,12 @@
     // code elimination doesn't optimize away anything we're testing.
     // We'll use it to compute the return code of the executable to make
     // sure it's needed.
- LIVE_CODE_TYPE live_code;
+ BOOST_SPIRIT_TEST_LIVE_CODE_TYPE live_code;
 
     // Call objects of the given Accumulator type repeatedly with x as
     // an argument.
- template <class Accumulator, class Arg>
- void hammer(Arg const& x, long const repeats)
+ template <class Accumulator>
+ void hammer(long const repeats)
     {
         // Strategy: because the sum in an accumulator after each call
         // depends on the previous value of the sum, the CPU's pipeline
@@ -50,6 +55,8 @@
         // or L3 cache, or main memory, you can increase the size of
         // this array. 1024 is an upper limit on the pipeline depth of
         // current vector machines.
+
+ typename Accumulator::type x = Accumulator::initial();
         const std::size_t number_of_accumulators = 1024;
         live_code = 0; // reset to zero
 
@@ -59,7 +66,7 @@
         {
             for (Accumulator* ap = a; ap < a + number_of_accumulators; ++ap)
             {
- (*ap)(x);
+ ap->benchmark(x);
             }
         }
 
@@ -73,42 +80,46 @@
 
     // Measure the time required to hammer accumulators of the given
     // type with the argument x.
- template <class Accumulator, class T>
- double measure(T const& x, long const repeats)
+ template <class Accumulator>
+ double measure(long const repeats)
     {
         // Hammer accumulators a couple of times to ensure the
         // instruction cache is full of our test code, and that we don't
         // measure the cost of a page fault for accessing the data page
         // containing the memory where the accumulators will be
         // allocated
- hammer<Accumulator>(x, repeats);
- hammer<Accumulator>(x, repeats);
+ hammer<Accumulator>(repeats);
+ hammer<Accumulator>(repeats);
 
         // Now start a timer
         util::high_resolution_timer time;
- hammer<Accumulator>(x, repeats); // This time, we'll measure
+ hammer<Accumulator>(repeats); // This time, we'll measure
         return time.elapsed() / repeats; // return the time of one iteration
     }
-
- template <typename Accumulator>
- static int run(typename Accumulator::type& result, double& base_time, long repeats = 100)
- {
- double measured = 0;
- while (measured < 2.0 && repeats <= 10000000)
- {
- repeats *= 10;
- util::high_resolution_timer time;
- test::hammer<Accumulator>(0, repeats);
- measured = time.elapsed();
- }
-
- test::measure<Accumulator>(1, 1);
- result = test::live_code;
- base_time = test::measure<Accumulator>(1, repeats);
-
- // This is ultimately responsible for preventing all the test code
- // from being optimized away. Change this to return 0 and you
- // unplug the whole test's life support system.
- return test::live_code != 0;
- }
+
+#define BOOST_SPIRIT_TEST_HAMMER(r, data, elem) \
+ test::hammer<elem>(repeats);
+ /***/
+
+#define BOOST_SPIRIT_TEST_MEASURE(r, data, elem) \
+ std::cout \
+ << BOOST_PP_STRINGIZE(elem) << ": " \
+ << test::measure<elem>(repeats) \
+ << std::endl;
+ /***/
+
+#define BOOST_SPIRIT_TEST_BENCHMARK(max_repeats, FSeq) \
+ long repeats = 100; \
+ double measured = 0; \
+ while (measured < 2.0 && repeats <= max_repeats) \
+ { \
+ repeats *= 10; \
+ util::high_resolution_timer time; \
+ BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_TEST_HAMMER, _, FSeq) \
+ measured = time.elapsed(); \
+ } \
+ BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_TEST_MEASURE, _, FSeq) \
+ /***/
 }
+
+#endif
\ No newline at end of file

Modified: trunk/libs/spirit/benchmarks/qi/uint_parser.cpp
==============================================================================
--- trunk/libs/spirit/benchmarks/qi/uint_parser.cpp (original)
+++ trunk/libs/spirit/benchmarks/qi/uint_parser.cpp 2009-07-22 12:54:20 EDT (Wed, 22 Jul 2009)
@@ -3,206 +3,40 @@
 
     Distributed under the Boost Software License, Version 1.0. (See accompanying
     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-=============================================================================*/
-#if defined(BOOST_MSVC)
-#pragma inline_depth(255)
-#pragma inline_recursion(on)
-#define _SECURE_SCL 0
-#endif // defined(BOOST_MSVC)
-
-#include "../high_resolution_timer.hpp"
-#include <boost/spirit/include/qi.hpp>
-#include <boost/lexical_cast.hpp>
-#include <climits>
-#include <cstdlib>
-#include <string>
-#include <vector>
-#include <sstream>
+==============================================================================*/
+#include "measure.hpp"
+#include <iostream>
 
-#define MAX_ITERATION 1000000
-
-void check(int a, int b)
+namespace
 {
- if (a != b)
- {
- std::cout << "Parse Error, got: " << a << " and " << b << std::endl;
- abort();
- }
-}
-
-int main()
-{
- namespace qi = boost::spirit::qi;
- using qi::int_;
-
- std::cout << "initializing input strings..." << std::endl;
- std::vector<int> src(MAX_ITERATION);
- std::vector<std::string> src_str(MAX_ITERATION);
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- src[i] = std::rand() * std::rand();
- if (std::rand() % 2)
- src[i] = -src[i];
- src_str[i] = boost::lexical_cast<std::string>(src[i]);
- }
-
- // test the C libraries atoi function (the most low level function for
- // string conversion available)
- {
- std::vector<int> v(MAX_ITERATION);
- std::vector<char const*> f(MAX_ITERATION);
-
- // get the C string
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- f[i] = src_str[i].c_str();
- }
-
- util::high_resolution_timer t;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- v[i] = atoi(f[i]);
- }
-
- std::cout << "atoi: " << t.elapsed() << " [s]" << std::flush << std::endl;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- check(v[i], src[i]);
- }
- }
-
- // test the C libraries strtol function (the most low level function for
- // string conversion available)
- {
- std::vector<int> v(MAX_ITERATION);
- std::vector<char const*> f(MAX_ITERATION);
-
- // get the C string
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- f[i] = src_str[i].c_str();
- }
-
- util::high_resolution_timer t;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- v[i] = strtol(f[i], 0, 10);
- }
-
- std::cout << "strtol: " << t.elapsed() << " [s]" << std::flush << std::endl;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- check(v[i], src[i]);
- }
- }
-
- // test sscanf
- {
- std::vector<int> v(MAX_ITERATION);
- std::vector<char const*> f(MAX_ITERATION);
-
- // get the C string
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- f[i] = src_str[i].c_str();
- }
-
- util::high_resolution_timer t;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- sscanf(f[i], "%d", &v[i]);
- }
-
- std::cout << "sscanf: " << t.elapsed() << " [s]" << std::flush << std::endl;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- check(v[i], src[i]);
- }
- }
-
- // test iostream
+ struct f
     {
- std::istringstream ss;
- std::vector<int> v(MAX_ITERATION);
- util::high_resolution_timer t;
+ typedef int type;
 
- for (int i = 0; i < MAX_ITERATION; ++i)
+ void operator()(int x)
         {
- ss.clear();
- ss.str(src_str[i]);
- ss >> v[i];
+ this->val ^= x; // here is where you put code that you want
+ // to benchmark. Make sure it returns something.
+ // Anything.
         }
 
- std::cout << "std::iostream: " << t.elapsed() << " [s]" << std::flush << std::endl;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- check(v[i], src[i]);
- }
- }
-
- // test boost::lexical_cast
- {
- std::vector<int> v(MAX_ITERATION);
- std::vector<char const*> f(MAX_ITERATION);
-
- // get the C string
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- f[i] = src_str[i].c_str();
- }
-
- util::high_resolution_timer t;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- v[i] = boost::lexical_cast<int>(src[i]);
- }
-
- std::cout << "boost::lexical_cast: " << t.elapsed() << " [s]" << std::flush << std::endl;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- check(v[i], src[i]);
- }
- }
-
- // test the Qi int_ parser routines
- {
- std::vector<int> v(MAX_ITERATION);
- std::vector<char const*> f(MAX_ITERATION);
- std::vector<char const*> l(MAX_ITERATION);
-
- // get the first/last iterators
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- f[i] = src_str[i].c_str();
- l[i] = f[i];
- while (*l[i])
- l[i]++;
- }
-
- util::high_resolution_timer t;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- qi::parse(f[i], l[i], int_, v[i]);
- }
+ int val; // this is where the value is accumulated
+ };
+}
 
- std::cout << "spirit int_: " << t.elapsed() << " [s]" << std::flush << std::endl;
-
- for (int i = 0; i < MAX_ITERATION; ++i)
- {
- check(v[i], src[i]);
- }
- }
+int main()
+{
+ int result;
+ double base_time;
+ int ret = test::run<f>(result, base_time, 100);
+
+ std::cout
+ << "f accumulated result: "
+ << result
+ << std::endl
+ << "f time: "
+ << base_time
+ << std::endl;
 
- return 0;
+ return ret;
 }
-


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk