forked from boostorg/conversion
Commited sources of performance testing program and Jamfile.v2 to build and run it
[SVN r76936]
This commit is contained in:
29
perf/Jamfile.v2
Normal file
29
perf/Jamfile.v2
Normal file
@@ -0,0 +1,29 @@
|
||||
#==============================================================================
|
||||
# Copyright (c) 2012 Antony Polukhin
|
||||
#
|
||||
# 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)
|
||||
#==============================================================================
|
||||
|
||||
# performance tests
|
||||
import testing ;
|
||||
import path ;
|
||||
|
||||
path-constant TEST_DIR : . ;
|
||||
|
||||
project performance/test
|
||||
: source-location ./
|
||||
: requirements
|
||||
# <library>/boost/chrono//boost_chrono
|
||||
# <library>/boost/system//boost_system
|
||||
<link>static
|
||||
<target-os>freebsd:<linkflags>"-lrt"
|
||||
<target-os>linux:<linkflags>"-lrt"
|
||||
<toolset>gcc:<cxxflags>-fvisibility=hidden
|
||||
<toolset>intel-linux:<cxxflags>-fvisibility=hidden
|
||||
<toolset>sun:<cxxflags>-xldscope=hidden
|
||||
: default-build release
|
||||
;
|
||||
|
||||
run performance_test.cpp : $(TEST_DIR) ;
|
||||
|
309
perf/performance_test.cpp
Normal file
309
perf/performance_test.cpp
Normal file
@@ -0,0 +1,309 @@
|
||||
// (C) Copyright Antony Polukhin 2012.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
// See http://www.boost.org/libs/config for most recent version.
|
||||
|
||||
//
|
||||
// Testing lexical_cast<> performance
|
||||
//
|
||||
|
||||
#define BOOST_ERROR_CODE_HEADER_ONLY
|
||||
#define BOOST_CHRONO_HEADER_ONLY
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/chrono.hpp>
|
||||
#include <fstream>
|
||||
#include <boost/container/string.hpp>
|
||||
|
||||
// File to output data
|
||||
std::fstream fout;
|
||||
|
||||
template <class OutT, class InT>
|
||||
static inline void test_lexical(const InT& in_val) {
|
||||
OutT out_val = boost::lexical_cast<OutT>(in_val);
|
||||
(void)out_val;
|
||||
}
|
||||
|
||||
template <class OutT, class InT>
|
||||
static inline void test_ss_constr(const InT& in_val) {
|
||||
OutT out_val;
|
||||
std::stringstream ss;
|
||||
ss << in_val;
|
||||
if (ss.fail()) throw std::logic_error("descr");
|
||||
ss >> out_val;
|
||||
if (ss.fail()) throw std::logic_error("descr");
|
||||
}
|
||||
|
||||
template <class OutT, class StringStreamT, class InT>
|
||||
static inline void test_ss_noconstr(StringStreamT& ss, const InT& in_val) {
|
||||
OutT out_val;
|
||||
ss << in_val; // ss is an instance of std::stringstream
|
||||
if (ss.fail()) throw std::logic_error("descr");
|
||||
ss >> out_val;
|
||||
if (ss.fail()) throw std::logic_error("descr");
|
||||
/* reseting std::stringstream to use it again */
|
||||
ss.str(std::string());
|
||||
ss.clear();
|
||||
}
|
||||
|
||||
struct structure_sprintf {
|
||||
template <class OutT, class BufferT, class InT>
|
||||
static inline void test(BufferT* buffer, const InT& in_val, const char* const conv) {
|
||||
sprintf(buffer, conv, in_val);
|
||||
OutT out_val(buffer);
|
||||
}
|
||||
|
||||
template <class OutT, class BufferT>
|
||||
static inline void test(BufferT* buffer, const std::string& in_val, const char* const conv) {
|
||||
sprintf(buffer, conv, in_val.c_str());
|
||||
OutT out_val(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
struct structure_sscanf {
|
||||
template <class OutT, class BufferT, class InT>
|
||||
static inline void test(BufferT* /*buffer*/, const InT& in_val, const char* const conv) {
|
||||
OutT out_val;
|
||||
sscanf(reinterpret_cast<const char*>(in_val), conv, &out_val);
|
||||
}
|
||||
|
||||
template <class OutT, class BufferT>
|
||||
static inline void test(BufferT* /*buffer*/, const std::string& in_val, const char* const conv) {
|
||||
OutT out_val;
|
||||
sscanf(in_val.c_str(), conv, &out_val);
|
||||
}
|
||||
};
|
||||
|
||||
struct structure_fake {
|
||||
template <class OutT, class BufferT, class InT>
|
||||
static inline void test(BufferT* /*buffer*/, const InT& /*in_val*/, const char* const /*conv*/) {}
|
||||
};
|
||||
|
||||
static const int fake_test_value = 9999;
|
||||
|
||||
template <class T>
|
||||
static inline void min_fancy_output(T v1, T v2, T v3, T v4) {
|
||||
const char beg_mark[] = "!!! *";
|
||||
const char end_mark[] = "* !!!";
|
||||
const char no_mark[] = "";
|
||||
|
||||
unsigned int res = 4;
|
||||
if (v1 < v2 && v1 < v3 && v1 < v4) res = 1;
|
||||
if (v2 < v1 && v2 < v3 && v2 < v4) res = 2;
|
||||
if (v3 < v1 && v3 < v2 && v3 < v4) res = 3;
|
||||
|
||||
fout << "[ "
|
||||
<< (res == 1 ? beg_mark : no_mark)
|
||||
;
|
||||
|
||||
if (v1) fout << v1;
|
||||
else fout << "<1";
|
||||
|
||||
fout << (res == 1 ? end_mark : no_mark)
|
||||
<< " ][ "
|
||||
<< (res == 2 ? beg_mark : no_mark)
|
||||
;
|
||||
|
||||
if (v2) fout << v2;
|
||||
else fout << "<1";
|
||||
|
||||
fout << (res == 2 ? end_mark : no_mark)
|
||||
<< " ][ "
|
||||
<< (res == 3 ? beg_mark : no_mark)
|
||||
;
|
||||
|
||||
if (v3) fout << v3;
|
||||
else fout << "<1";
|
||||
|
||||
fout << (res == 3 ? end_mark : no_mark)
|
||||
<< " ][ "
|
||||
<< (res == 4 ? beg_mark : no_mark)
|
||||
;
|
||||
|
||||
if (!v4) fout << "<1";
|
||||
else if (v4 == fake_test_value) fout << "---";
|
||||
else fout << v4;
|
||||
|
||||
fout
|
||||
<< (res == 4 ? end_mark : no_mark)
|
||||
<< " ]";
|
||||
}
|
||||
|
||||
template <unsigned int IetartionsCountV, class ToT, class SprintfT, class FromT>
|
||||
static inline void perf_test_impl(const FromT& in_val, const char* const conv) {
|
||||
|
||||
typedef boost::chrono::steady_clock test_clock;
|
||||
test_clock::time_point start;
|
||||
typedef boost::chrono::milliseconds duration_t;
|
||||
duration_t lexical_cast_time, ss_constr_time, ss_noconstr_time, printf_time;
|
||||
|
||||
start = test_clock::now();
|
||||
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
|
||||
test_lexical<ToT>(in_val);
|
||||
test_lexical<ToT>(in_val);
|
||||
test_lexical<ToT>(in_val);
|
||||
test_lexical<ToT>(in_val);
|
||||
}
|
||||
lexical_cast_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
|
||||
|
||||
|
||||
start = test_clock::now();
|
||||
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
|
||||
test_ss_constr<ToT>(in_val);
|
||||
test_ss_constr<ToT>(in_val);
|
||||
test_ss_constr<ToT>(in_val);
|
||||
test_ss_constr<ToT>(in_val);
|
||||
}
|
||||
ss_constr_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
|
||||
|
||||
std::stringstream ss;
|
||||
start = test_clock::now();
|
||||
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
|
||||
test_ss_noconstr<ToT>(ss, in_val);
|
||||
test_ss_noconstr<ToT>(ss, in_val);
|
||||
test_ss_noconstr<ToT>(ss, in_val);
|
||||
test_ss_noconstr<ToT>(ss, in_val);
|
||||
}
|
||||
ss_noconstr_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
|
||||
|
||||
|
||||
char buffer[128];
|
||||
start = test_clock::now();
|
||||
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
|
||||
SprintfT::template test<ToT>(buffer, in_val, conv);
|
||||
SprintfT::template test<ToT>(buffer, in_val, conv);
|
||||
SprintfT::template test<ToT>(buffer, in_val, conv);
|
||||
SprintfT::template test<ToT>(buffer, in_val, conv);
|
||||
}
|
||||
printf_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
|
||||
|
||||
min_fancy_output(
|
||||
lexical_cast_time.count(),
|
||||
ss_constr_time.count(),
|
||||
ss_noconstr_time.count(),
|
||||
boost::is_same<SprintfT, structure_fake>::value ? fake_test_value : printf_time.count()
|
||||
);
|
||||
}
|
||||
|
||||
template <class ToT, class SprintfT, class FromT>
|
||||
static inline void perf_test(const std::string& test_name, const FromT& in_val, const char* const conv) {
|
||||
const unsigned int ITERATIONSCOUNT = 100000;
|
||||
fout << " [[ " << test_name << " ]";
|
||||
|
||||
perf_test_impl<ITERATIONSCOUNT/4, ToT, SprintfT>(in_val, conv);
|
||||
|
||||
fout << "]\n";
|
||||
}
|
||||
|
||||
|
||||
template <class ConverterT>
|
||||
void string_like_test_set(const std::string& from) {
|
||||
typedef structure_sscanf ssc_t;
|
||||
ConverterT conv;
|
||||
|
||||
perf_test<char, ssc_t>(from + "->char", conv("c"), "%c");
|
||||
perf_test<signed char, ssc_t>(from + "->signed char", conv("c"), "%hhd");
|
||||
perf_test<unsigned char, ssc_t>(from + "->unsigned char", conv("c"), "%hhu");
|
||||
|
||||
perf_test<int, ssc_t>(from + "->int", conv("100"), "%d");
|
||||
perf_test<short, ssc_t>(from + "->short", conv("100"), "%hd");
|
||||
perf_test<long int, ssc_t>(from + "->long int", conv("100"), "%ld");
|
||||
perf_test<boost::long_long_type, ssc_t>(from + "->long long", conv("100"), "%lld");
|
||||
|
||||
perf_test<unsigned int, ssc_t>(from + "->unsigned int", conv("100"), "%u");
|
||||
perf_test<unsigned short, ssc_t>(from + "->unsigned short", conv("100"), "%hu");
|
||||
perf_test<unsigned long int, ssc_t>(from + "->unsigned long int", conv("100"), "%lu");
|
||||
perf_test<boost::ulong_long_type, ssc_t>(from + "->unsigned long long", conv("100"), "%llu");
|
||||
|
||||
// perf_test<bool, ssc_t>(from + "->bool", conv("1"), "%");
|
||||
|
||||
perf_test<float, ssc_t>(from + "->float", conv("1.123"), "%f");
|
||||
perf_test<double, ssc_t>(from + "->double", conv("1.123"), "%lf");
|
||||
perf_test<long double, ssc_t>(from + "->long double", conv("1.123"), "%Lf");
|
||||
|
||||
|
||||
perf_test<std::string, structure_fake>(from + "->string", conv("string"), "%Lf");
|
||||
perf_test<boost::container::string, structure_fake>(from + "->container::string"
|
||||
, conv("string"), "%Lf");
|
||||
|
||||
}
|
||||
|
||||
struct to_string_conv {
|
||||
std::string operator()(const char* const c) const {
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
struct to_char_conv {
|
||||
const char* operator()(const char* const c) const {
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
struct to_uchar_conv {
|
||||
const unsigned char* operator()(const char* const c) const {
|
||||
return reinterpret_cast<const unsigned char*>(c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct to_schar_conv {
|
||||
const signed char* operator()(const char* const c) const {
|
||||
return reinterpret_cast<const signed char*>(c);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
BOOST_ASSERT(argc >= 2);
|
||||
std::string output_path(argv[1]);
|
||||
output_path += "/results.txt";
|
||||
fout.open(output_path.c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
|
||||
BOOST_ASSERT(fout);
|
||||
|
||||
fout << "[section " << BOOST_COMPILER << "]\n"
|
||||
<< "[table:id Performance Table ( "<< BOOST_COMPILER << ")\n"
|
||||
<< "[[From->To] [lexical_cast] [std::stringstream with construction] "
|
||||
<< "[std::stringstream without construction][scanf/printf]]\n";
|
||||
|
||||
|
||||
// From std::string to ...
|
||||
string_like_test_set<to_string_conv>("string");
|
||||
|
||||
// From ... to std::string
|
||||
perf_test<std::string, structure_sprintf>("string->char", 'c', "%c");
|
||||
perf_test<std::string, structure_sprintf>("string->signed char", static_cast<signed char>('c'), "%hhd");
|
||||
perf_test<std::string, structure_sprintf>("string->unsigned char", static_cast<unsigned char>('c'), "%hhu");
|
||||
|
||||
perf_test<std::string, structure_sprintf>("int->string", 100, "%d");
|
||||
perf_test<std::string, structure_sprintf>("short->string", static_cast<short>(100), "%hd");
|
||||
perf_test<std::string, structure_sprintf>("long int->string", 100l, "%ld");
|
||||
perf_test<std::string, structure_sprintf>("long long->string", 100ll, "%lld");
|
||||
|
||||
perf_test<std::string, structure_sprintf>("unsigned int->string", static_cast<unsigned short>(100u), "%u");
|
||||
perf_test<std::string, structure_sprintf>("unsigned short->string", 100u, "%hu");
|
||||
perf_test<std::string, structure_sprintf>("unsigned long int->string", 100ul, "%lu");
|
||||
perf_test<std::string, structure_sprintf>("unsigned long long->string", static_cast<boost::ulong_long_type>(100), "%llu");
|
||||
|
||||
// perf_test<bool, structure_sscanf>("bool->string", std::string("1"), "%");
|
||||
|
||||
perf_test<std::string, structure_sprintf>("float->string", 1.123f, "%f");
|
||||
perf_test<std::string, structure_sprintf>("double->string", 1.123, "%lf");
|
||||
perf_test<std::string, structure_sprintf>("long double->string", 1.123L, "%Lf");
|
||||
|
||||
|
||||
string_like_test_set<to_char_conv>("char*");
|
||||
string_like_test_set<to_uchar_conv>("unsigned char*");
|
||||
string_like_test_set<to_schar_conv>("signed char*");
|
||||
|
||||
perf_test<int, structure_fake>("int->int", 100, "");
|
||||
perf_test<double, structure_fake>("float->double", 100.0f, "");
|
||||
perf_test<signed char, structure_fake>("char->signed char", 'c', "");
|
||||
|
||||
fout << "]\n"
|
||||
<< "[endsect]\n\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user