Squashed 'third_party/boostorg/format/' content from commit a1c6137
Change-Id: I7c2f1d4813c1e733fcf553b4ed9c418e661b0ea8
git-subtree-dir: third_party/boostorg/format
git-subtree-split: a1c613764dd96f97749e1e059c80f0f3515fcf0b
diff --git a/benchmark/bench_format.cpp b/benchmark/bench_format.cpp
new file mode 100644
index 0000000..393df75
--- /dev/null
+++ b/benchmark/bench_format.cpp
@@ -0,0 +1,356 @@
+// -*- 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;
+}
+