123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- // Boost.Convert test and usage example
- // Copyright (c) 2009-2016 Vladimir Batov.
- // Use, modification and distribution are subject to the Boost Software License,
- // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
- #include "./test.hpp"
- #if defined(BOOST_CONVERT_IS_NOT_SUPPORTED)
- int main(int, char const* []) { return 0; }
- #else
- #include "./prepare.hpp"
- #include <boost/convert.hpp>
- #include <boost/convert/stream.hpp>
- #include <boost/convert/printf.hpp>
- #include <boost/convert/strtol.hpp>
- #include <boost/convert/spirit.hpp>
- #include <boost/convert/lexical_cast.hpp>
- #include <boost/detail/lightweight_test.hpp>
- #include <boost/timer/timer.hpp>
- #include <boost/array.hpp>
- #include <boost/random/mersenne_twister.hpp>
- #include <boost/random/uniform_int_distribution.hpp>
- #include <cstdlib>
- #include <cstdio>
- using std::string;
- using boost::convert;
- namespace cnv = boost::cnv;
- namespace arg = boost::cnv::parameter;
- namespace { namespace local
- {
- template<typename Type>
- struct array
- {
- typedef boost::array<Type, 20> type;
- };
- template<typename T> static typename array<T>::type const& get();
- static int const num_cycles = 1000000;
- int sum = 0;
- struct timer : public boost::timer::cpu_timer
- {
- typedef timer this_type;
- typedef boost::timer::cpu_timer base_type;
- double value() const
- {
- boost::timer::cpu_times times = base_type::elapsed();
- int const use_sum = (sum % 2) ? 0 : (sum % 2); BOOST_TEST(use_sum == 0);
- return double(times.user + times.system) / 1000000000 + use_sum;
- }
- };
- template< typename Type, typename Cnv> static double str_to (Cnv const&);
- template<typename S, typename Type, typename Cnv> static double to_str (Cnv const&);
- template<>
- local::array<int>::type const&
- get<int>()
- {
- static array<int>::type ints;
- static bool filled;
- if (!filled)
- {
- boost::random::mt19937 gen (::time(0));
- boost::random::uniform_int_distribution<> dist (INT_MIN, INT_MAX); // INT_MAX(32) = 2,147,483,647
- for (size_t k = 0; k < ints.size(); ++k)
- ints[k] = dist(gen);
- filled = true;
- }
- return ints;
- }
- template<>
- array<long int>::type const&
- get<long int>()
- {
- static array<long int>::type ints;
- static bool filled;
- if (!filled)
- {
- boost::random::mt19937 gen (::time(0));
- boost::random::uniform_int_distribution<> dist (INT_MIN, INT_MAX); // INT_MAX(32) = 2147483647
- for (size_t k = 0; k < ints.size(); ++k)
- ints[k] = dist(gen);
- filled = true;
- }
- return ints;
- }
- template<>
- array<double>::type const&
- get<double>()
- {
- static array<double>::type dbls;
- static bool filled;
- if (!filled)
- {
- boost::random::mt19937 gen (::time(0));
- boost::random::uniform_int_distribution<> dist (INT_MIN, INT_MAX); // INT_MAX(32) = 2147483647
- for (size_t k = 0; k < dbls.size(); ++k)
- dbls[k] = double(dist(gen)) + 0.7654321;
- filled = true;
- }
- return dbls;
- }
- }}
- struct raw_str_to_int_spirit
- {
- int operator()(char const* str) const
- {
- char const* beg = str;
- char const* end = beg + strlen(str);
- int result;
- if (boost::spirit::qi::parse(beg, end, boost::spirit::int_, result))
- if (beg == end) // ensure the whole string was parsed
- return result;
- return (BOOST_ASSERT(0), result);
- }
- };
- struct raw_str_to_int_lxcast
- {
- int operator()(char const* str) const
- {
- return boost::lexical_cast<int>(str);
- }
- };
- template<typename Type, typename Converter>
- double
- raw_str_to(Converter const& cnv)
- {
- local::strings strings = local::get_strs(); // Create strings on the stack
- int const size = strings.size();
- local::timer timer;
- for (int t = 0; t < local::num_cycles; ++t)
- for (int k = 0; k < size; ++k)
- local::sum += cnv(strings[k].c_str());
- return timer.value();
- }
- template<typename Type, typename Converter>
- double
- local::str_to(Converter const& try_converter)
- {
- local::strings strings = local::get_strs(); // Create strings on the stack
- int const size = strings.size();
- local::timer timer;
- for (int t = 0; t < local::num_cycles; ++t)
- for (int k = 0; k < size; ++k)
- local::sum += boost::convert<Type>(strings[k].c_str(), try_converter).value();
- return timer.value();
- }
- template<typename string_type, typename Type, typename Converter>
- double
- local::to_str(Converter const& try_converter)
- {
- typedef typename local::array<Type>::type collection;
- collection values = local::get<Type>();
- int const size = values.size();
- local::timer timer;
- for (int t = 0; t < local::num_cycles; ++t)
- for (int k = 0; k < size; ++k)
- local::sum += *boost::convert<string_type>(Type(values[k]), try_converter).value().begin();
- return timer.value();
- }
- template<typename Converter>
- double
- performance_str_to_type(Converter const& try_converter)
- {
- char const* input[] = { "no", "up", "dn" };
- local::timer timer;
- for (int k = 0; k < local::num_cycles; ++k)
- {
- change chg = boost::convert<change>(input[k % 3], try_converter).value();
- int res = chg.value();
- BOOST_TEST(res == k % 3);
- local::sum += res; // Make sure chg is not optimized out
- }
- return timer.value();
- }
- template<typename Converter>
- double
- performance_type_to_str(Converter const& try_converter)
- {
- boost::array<change, 3> input = {{ change::no, change::up, change::dn }};
- boost::array<string, 3> results = {{ "no", "up", "dn" }};
- local::timer timer;
- for (int k = 0; k < local::num_cycles; ++k)
- {
- string res = boost::convert<string>(input[k % 3], try_converter).value();
- BOOST_TEST(res == results[k % 3]);
- local::sum += res[0]; // Make sure res is not optimized out
- }
- return timer.value();
- }
- template<typename Raw, typename Cnv>
- void
- performance_comparative(Raw const& raw, Cnv const& cnv, char const* txt)
- {
- int const num_tries = 5;
- double cnv_time = 0;
- double raw_time = 0;
- for (int k = 0; k < num_tries; ++k) cnv_time += local::str_to<int>(cnv);
- for (int k = 0; k < num_tries; ++k) raw_time += raw_str_to<int>(raw);
- cnv_time /= num_tries;
- raw_time /= num_tries;
- double change = 100 * (1 - cnv_time / raw_time);
- printf("str-to-int: %s raw/cnv=%.2f/%.2f seconds (%.2f%%).\n", txt, raw_time, cnv_time, change);
- }
- int
- main(int, char const* [])
- {
- printf("Started performance tests...\n");
- printf("str-to-int: spirit/strtol/lcast/scanf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
- local::str_to<int>(boost::cnv::spirit()),
- local::str_to<int>(boost::cnv::strtol()),
- local::str_to<int>(boost::cnv::lexical_cast()),
- local::str_to<int>(boost::cnv::printf()),
- local::str_to<int>(boost::cnv::cstream()));
- printf("str-to-lng: spirit/strtol/lcast/scanf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
- local::str_to<long int>(boost::cnv::spirit()),
- local::str_to<long int>(boost::cnv::strtol()),
- local::str_to<long int>(boost::cnv::lexical_cast()),
- local::str_to<long int>(boost::cnv::printf()),
- local::str_to<long int>(boost::cnv::cstream()));
- printf("str-to-dbl: spirit/strtol/lcast/scanf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
- local::str_to<double>(boost::cnv::spirit()),
- local::str_to<double>(boost::cnv::strtol()),
- local::str_to<double>(boost::cnv::lexical_cast()),
- local::str_to<double>(boost::cnv::printf()),
- local::str_to<double>(boost::cnv::cstream()));
- printf("int-to-str: spirit/strtol/lcast/prntf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
- local::to_str<std::string, int>(boost::cnv::spirit()),
- local::to_str<std::string, int>(boost::cnv::strtol()),
- local::to_str<std::string, int>(boost::cnv::lexical_cast()),
- local::to_str<std::string, int>(boost::cnv::printf()),
- local::to_str<std::string, int>(boost::cnv::cstream()));
- printf("lng-to-str: spirit/strtol/lcast/prntf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
- local::to_str<std::string, long int>(boost::cnv::spirit()),
- local::to_str<std::string, long int>(boost::cnv::strtol()),
- local::to_str<std::string, long int>(boost::cnv::lexical_cast()),
- local::to_str<std::string, long int>(boost::cnv::printf()),
- local::to_str<std::string, long int>(boost::cnv::cstream()));
- printf("dbl-to-str: spirit/strtol/lcast/prntf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
- local::to_str<std::string, double>(boost::cnv::spirit()),
- local::to_str<std::string, double>(boost::cnv::strtol()(arg::precision = 6)),
- local::to_str<std::string, double>(boost::cnv::lexical_cast()),
- local::to_str<std::string, double>(boost::cnv::printf()(arg::precision = 6)),
- local::to_str<std::string, double>(boost::cnv::cstream()(arg::precision = 6)));
- printf("str-to-user-type: lcast/stream/strtol=%.2f/%.2f/%.2f seconds.\n",
- performance_str_to_type(boost::cnv::lexical_cast()),
- performance_str_to_type(boost::cnv::cstream()),
- performance_str_to_type(boost::cnv::strtol()));
- printf("user-type-to-str: lcast/stream/strtol=%.2f/%.2f/%.2f seconds.\n",
- performance_type_to_str(boost::cnv::lexical_cast()),
- performance_type_to_str(boost::cnv::cstream()),
- performance_type_to_str(boost::cnv::strtol()));
- //[small_string_results
- printf("strtol int-to std::string/small-string: %.2f/%.2f seconds.\n",
- local::to_str<std::string, int>(boost::cnv::strtol()),
- local::to_str< my_string, int>(boost::cnv::strtol()));
- printf("spirit int-to std::string/small-string: %.2f/%.2f seconds.\n",
- local::to_str<std::string, int>(boost::cnv::spirit()),
- local::to_str< my_string, int>(boost::cnv::spirit()));
- printf("stream int-to std::string/small-string: %.2f/%.2f seconds.\n",
- local::to_str<std::string, int>(boost::cnv::cstream()),
- local::to_str< my_string, int>(boost::cnv::cstream()));
- //]
- performance_comparative(raw_str_to_int_spirit(), boost::cnv::spirit(), "spirit");
- performance_comparative(raw_str_to_int_lxcast(), boost::cnv::lexical_cast(), "lxcast");
- return boost::report_errors();
- }
- #endif
|