/*============================================================================= Copyright (c) 2001-2009 Joel de Guzman 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) =============================================================================*/ // // Modified by Edward Grace to try out my timer on a real-world // example of someone else. // #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 #incldue #include #include #include #include #include #include #define MAX_ITERATION 1000//0000 // This (surprisingly) is good enough! It's not high resolution, but // should do the trick! microsecond usec_chrono() { timeval tp; gettimeofday(&tp,NULL); return tp.tv_sec*1000000 + tp.tv_usec; } // Not bothering with this for the moment. void check(int a, int b) { if (a != b) { std::cout << "Parse Error" << std::endl; abort(); } } // Global variables - prevention of compiler optimisation of the void // atoi() and void strtol() functions below. std::vector src(MAX_ITERATION); std::vector src_str(MAX_ITERATION); std::vector v(MAX_ITERATION); // Build a function that tests atoi inline void atoi() { for (int i = 0; i < MAX_ITERATION; ++i) v[i] = atoi(src_str[i].c_str()); } // Build a function that tests strtol inline void strtol() { for (int i = 0; i < MAX_ITERATION; ++i) v[i] = strtol(src_str[i].c_str(), 0, 10); } // Again, global variables so that the optimizer doesn't turn the void // qi_parse() test function in to (literally) nothing. // // In future there would need to be a way of incorporating this type // of functionality in a simple manner. std::vector f(MAX_ITERATION); std::vector l(MAX_ITERATION); // Build a function that tests qi::parse inline void qi_parse() { for (int i = 0; i < MAX_ITERATION; ++i) boost::spirit::qi::parse(f[i], l[i], boost::spirit::qi::int_, v[i]); } int main() { namespace qi = boost::spirit::qi; using qi::int_; std::cout << "initializing input strings..." << std::endl; for (int i = 0; i < MAX_ITERATION; ++i) { src[i] = std::rand() * std::rand(); src_str[i] = boost::lexical_cast(src[i]); } // Build the first last iterators. // get the first/last iterators for (int i = 0; i < f.size(); ++i) { f[i] = src_str[i].c_str(); l[i] = f[i]; while (*l[i]) l[i]++; } // Build a timer based on gettimeofday - perhaps stick whatever // your util::high_resolution_timer is in here. The template // argument should be the return type of the timer function, the // constructor argument a function pointer. ejg::generic_timer timer(usec_chrono); // If the returned confidence bounds (min,max) include zero, you // may need to improve the nominal precision. The default should // be fine! // // timer.set_nominal_precision_target_percent(1.0); timer.calibrate(); // Not that important if the functions take a // long time to run relative to a call to the // clock // Test the C libraries atoi function against spirit. (the most // low level function for string conversion available) double min,med,max; timer.measure_percentage_speedup(qi_parse,atoi); std::cout << "qi_parse vs atoi :" << min << " " << med << " " << max << "% faster." << std::endl; // Race qi_parse and strtol. timer.measure_percentage_speedup(qi_parse,strtol); std::cout << "qi_parse vs strtol :" << min << " " << med << " " << max << "% faster." << std::endl; // Checking results since there's no way to do that when racing // the two in pairs. std::cout << "Checking that the results are correct...\n"; qi_parse(); for (int i=0; i < MAX_ITERATION; check(v[i], src[i]), ++i); std::cout << "qi is behaving itself!" << std::endl; atoi(); for (int i=0; i < MAX_ITERATION; check(v[i], src[i]), ++i); std::cout << "atoi is behaving itself!" << std::endl; strtol(); for (int i=0; i < MAX_ITERATION; check(v[i], src[i]), ++i); std::cout << "strtol is behaving itself!" << std::endl; std::cout << "\n\nAll done!\n"; return 0; }