123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- // -*- C++ -*-
- // Boost general library 'format' ---------------------------
- // See http://www.boost.org for updates, documentation, and revision history.
- // Copyright (c) 2001 Samuel Krempp
- // krempp@crans.ens-cachan.fr
- // 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)
- // several suggestions from Jens Maurer
- // ------------------------------------------------------------------------------
- // bench_variants.cc : do the same task, with sprintf, stream, and format
- // and compare their times.
- // This benchmark is provided purely for information.
- // It might not even compile as-is,
- // or not give any sensible results.
- // (e.g., it expects sprintf to be POSIX compliant)
- // ------------------------------------------------------------------------------
- #include <iostream>
- #include <iomanip>
- #include <cstdio> // sprintf
- #include <cstring>
- #include <fstream>
- #include <cmath> // floor
- #include <boost/timer.hpp>
- #include <vector>
- #include <boost/format.hpp>
- // portable /dev/null stream equivalent, by James Kanze, http://www.gabi-soft.de
- class NulStreambuf : public std::streambuf
- {
- public:
- NulStreambuf() {
- setp( dummyBuffer , dummyBuffer + 64 ) ;
- }
- virtual int overflow( int c );
- virtual int underflow();
- private:
- char dummyBuffer[ 64 ] ;
- } ;
- class NulStream : public std::basic_ostream<char, std::char_traits<char> >
- {
- public:
- NulStream();
- virtual ~NulStream();
- NulStreambuf* rdbuf() {
- return static_cast< NulStreambuf* >(
- ((std::basic_ostream<char, std::char_traits<char> > *) this) -> rdbuf() ) ;
- }
- } ;
-
- //-------------------------------------------------------------------------------------
- // NulStream implementation
- NulStream::NulStream() : std::basic_ostream<char, std::char_traits<char> > (NULL) {
- init( new NulStreambuf ) ;
- }
- NulStream::~NulStream() {
- delete rdbuf() ;
- }
- int NulStreambuf::underflow(){ return std::ios::traits_type::eof();
- }
- int NulStreambuf::overflow( int c ){
- setp( dummyBuffer , dummyBuffer + 64 ) ;
- return (c == std::ios::traits_type::eof()) ? '\0' : c ;
- }
- // -------------------------------------------------------------------------------------
- namespace benchmark {
- static int NTests = 300000;
- //static std::stringstream nullStream;
- static NulStream nullStream;
- static double tstream, tpf;
- //static const std::string fstring="%3$#x %1$20.10E %2$g %3$d \n";
- static const std::string fstring="%3$0#6x %1$20.10E %2$g %3$0+5d \n";
- static const double arg1=45.23;
- static const double arg2=12.34;
- static const int arg3=23;
- static const std::string res =
- "0x0017 4.5230000000E+01 12.34 +0023 \n";
- //static const std::string res = "23.0000 4.5230000000E+01 12.34 23 \n";
- void test_sprintf();
- void test_nullstream();
- void test_opti_nullstream();
- void test_parsed_once_format();
- void test_reused_format();
- void test_format();
- void test_try1();
- void test_try2();
- void test_sprintf()
- {
- using namespace std;
- vector<char> bufr;
- bufr.reserve(4000);
- char *buf = &bufr[0];
- // Check that sprintf is Unix98 compatible on the platform :
- sprintf(buf, fstring.c_str(), arg1, arg2, arg3);
- if( strncmp( buf, res.c_str(), res.size()) != 0 ) {
- cerr << endl << buf;
- }
- // time the loop :
- boost::timer chrono;
- for(int i=0; i<NTests; ++i) {
- sprintf(buf, fstring.c_str(), arg1, arg2, arg3);
- }
- tpf=chrono.elapsed();
- cout << left << setw(20) <<"printf time"<< right <<":" << tpf << endl;
- }
- void test_try1()
- {
- using namespace std;
- boost::io::basic_oaltstringstream<char> oss;
- oss << boost::format(fstring) % arg1 % arg2 % arg3;
- boost::timer chrono;
- size_t dummy=0;
- for(int i=0; i<NTests; ++i) {
- dummy += oss.cur_size();
- }
- double t = chrono.elapsed();
- cout << left << setw(20) <<"try1 time"<< right <<":" << setw(5) << t
- << ", = " << t / tpf << " * printf "
- << ", = " << t / tstream << " * nullStream \n";
- }
- void test_try2()
- {
- using namespace std;
- boost::io::basic_oaltstringstream<char> oss;
- oss << boost::format(fstring) % arg1 % arg2 % arg3;
- oss << "blas 34567890GGGGGGGGGGGGGGGGGGGGGGGGGGGGggggggggggggggggggggggggggg " << endl;
- string s = oss.cur_str();
- oss << s << s << s;
- oss.clear_buffer();
- oss << s << s;
- s = oss.cur_str();
- boost::timer chrono;
- size_t dummy=0;
- for(int i=0; i<NTests; ++i) {
- dummy += oss.cur_size();
- }
- double t = chrono.elapsed();
- cout << left << setw(20) <<"try2 time"<< right <<":" << setw(5) << t
- << ", = " << t / tpf << " * printf "
- << ", = " << t / tstream << " * nullStream \n";
- }
- void do_stream(std::ostream& os) {
- using namespace std;
- std::ios_base::fmtflags f = os.flags();
- os << hex << showbase << internal << setfill('0') << setw(6) << arg3
- << dec << noshowbase << right << setfill(' ')
- << " "
- << scientific << setw(20) << setprecision(10) << uppercase << arg1
- << setprecision(6) << nouppercase ;
- os.flags(f);
- os << " " << arg2 << " "
- << showpos << setw(5) << internal << setfill('0') << arg3 << " \n" ;
- os.flags(f);
- }
- void test_nullstream()
- {
- using namespace std;
- boost::timer chrono;
- boost::io::basic_oaltstringstream<char> oss;
- {
- do_stream(oss);
- if(oss.str() != res ) {
- cerr << endl << oss.str() ;
- }
- }
- for(int i=0; i<NTests; ++i) {
- do_stream(nullStream);
- }
- // for(int i=0; i<NTests; ++i) {
- // std::ios_base::fmtflags f0 = nullStream.flags();
- // nullStream << hex << showbase << arg3
- // << dec << noshowbase << " "
- // << scientific << setw(20) << setprecision(10) << uppercase << arg1
- // << setprecision(0);
- // nullStream.flags(f0);
- // nullStream << " " << arg2 << " " << arg3 << " \n" ;
- // }
- double t = chrono.elapsed();
- cout << left << setw(20) <<"ostream time"<< right <<":" << setw(5) << t
- << ", = " << t / tpf << " * printf \n";
- tstream = t;
- }
- void test_opti_nullstream()
- {
- using namespace std;
- boost::timer chrono;
- boost::io::basic_oaltstringstream<char> oss;
- //static const std::string fstring="%3$#x %1$20.10E %2$g %3$d \n";
- std::ios_base::fmtflags f0 = oss.flags(), f1, f2;
- streamsize p0 = oss.precision();
- {
- oss << hex << showbase;
- f1 = oss.flags();
- oss << arg3;
- oss.flags(f0);
- oss << " " << scientific << setw(20) << setprecision(10) << uppercase;
- f2 = oss.flags();
- oss << arg1;
- oss.flags(f0); oss.precision(p0);
- oss << " " << arg2 << " " << arg3 << " \n" ;
-
- if(oss.str() != res ) {
- cerr << endl << oss.str() ;
- }
- }
- for(int i=0; i<NTests; ++i) {
- nullStream.flags(f1);
- nullStream << arg3;
- nullStream << setw(20) << setprecision(10);
- nullStream.flags(f2);
- nullStream << arg1;
- nullStream.flags(f0); nullStream.precision(p0);
- nullStream << " " << arg2 << " " << arg3 << " \n" ;
- }
- double t = chrono.elapsed();
- cout << left << setw(20) <<"opti-stream time"<< right <<":" << setw(5) << t
- << ", = " << t / tpf << " * printf \n";
- // tstream = t;
- }
- void test_parsed_once_format()
- {
- using namespace std;
- static const boost::format fmter(fstring);
- boost::io::basic_oaltstringstream<char> oss;
- oss << boost::format(fmter) % arg1 % arg2 % arg3 ;
- if( oss.str() != res ) {
- cerr << endl << oss.str();
- }
- // not only is the format-string parsed once,
- // but also the buffer of the internal stringstream is already allocated.
- boost::timer chrono;
- for(int i=0; i<NTests; ++i) {
- nullStream << boost::format(fmter) % arg1 % arg2 % arg3;
- }
- double t=chrono.elapsed();
- cout << left << setw(20) <<"parsed-once time"<< right <<":" << setw(5) << t
- << ", = " << t / tpf << " * printf "
- << ", = " << t / tstream << " * nullStream \n";
- }
- void test_reused_format()
- {
- using namespace std;
- boost::io::basic_oaltstringstream<char> oss;
- oss << boost::format(fstring) % arg1 % arg2 % arg3;
- if(oss.str() != res ) {
- cerr << endl << oss.str();
- }
- boost::timer chrono;
- boost::format fmter;
- for(int i=0; i<NTests; ++i) {
- nullStream << fmter.parse(fstring) % arg1 % arg2 % arg3;
- }
- double t = chrono.elapsed();
- cout << left << setw(20) <<"reused format time"<< right <<":" << setw(5) << t
- << ", = " << t / tpf << " * printf "
- << ", = " << t / tstream << " * nullStream \n";
- }
- void test_format()
- {
- using namespace std;
- boost::io::basic_oaltstringstream<char> oss;
- oss << boost::format(fstring) % arg1 % arg2 % arg3;
- if(oss.str() != res ) {
- cerr << endl << oss.str();
- }
- boost::timer chrono;
- for(int i=0; i<NTests; ++i) {
- nullStream << boost::format(fstring) % arg1 % arg2 % arg3;
- }
- double t = chrono.elapsed();
- cout << left << setw(20) <<"format time"<< right <<":" << setw(5) << t
- << ", = " << t / tpf << " * printf "
- << ", = " << t / tstream << " * nullStream \n";
- }
- } // benchmark
- int main(int argc, char * argv[]) {
- using namespace benchmark;
- using namespace boost;
- using namespace std;
- const string::size_type npos = string::npos;
- string choices = "";
- if (1<argc) {
- choices = (argv[1]); // profiling is easier launching only one.
- NTests = 1000 * 1000; // andmoreprecise with many iterations
- cout << "choices (" << choices << ") \n";
- }
- if (choices == "" || choices.find('p') != npos)
- test_sprintf();
- if (choices == "" || choices.find('n') != npos)
- test_nullstream();
- if (choices == "" || choices.find('1') != npos)
- test_parsed_once_format();
- if (choices == "" || choices.find('r') != npos)
- test_reused_format();
- if (choices == "" || choices.find('f') != npos)
- test_format();
- if (choices.find('t') != npos)
- test_try1();
- if (choices.find('y') != npos)
- test_try2();
- if (choices.find('o') != npos)
- test_opti_nullstream();
- return 0;
- }
|