Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r54954 - trunk/libs/spirit/example/karma
From: hartmut.kaiser_at_[hidden]
Date: 2009-07-14 15:47:04


Author: hkaiser
Date: 2009-07-14 15:47:03 EDT (Tue, 14 Jul 2009)
New Revision: 54954
URL: http://svn.boost.org/trac/boost/changeset/54954

Log:
Spirit: added Karma performance measurements
Added:
   trunk/libs/spirit/example/karma/double_performance.cpp (contents, props changed)
   trunk/libs/spirit/example/karma/format_performance.cpp (contents, props changed)
   trunk/libs/spirit/example/karma/high_resolution_timer.hpp (contents, props changed)

Added: trunk/libs/spirit/example/karma/double_performance.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/karma/double_performance.cpp 2009-07-14 15:47:03 EDT (Tue, 14 Jul 2009)
@@ -0,0 +1,173 @@
+// Copyright (c) 2002-2009 Joel Hartmut Kaiser
+// Copyright (c) 2002-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)
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/format.hpp>
+
+#include <iostream>
+
+#include "high_resolution_timer.hpp"
+
+#define NUMITERATIONS 1000000
+
+///////////////////////////////////////////////////////////////////////////////
+// policy for real_generator, which forces to output trailing zeros in the
+// fractional part
+template <typename T>
+struct double3_policy : boost::spirit::karma::real_policies<T>
+{
+ // we want to generate up to 3 fractional digits
+ static unsigned int precision(T) { return 3; }
+};
+
+typedef boost::spirit::karma::real_generator<double, double3_policy<double> >
+ double3_type;
+double3_type const double3 = double3_type();
+
+void format_performance_karma()
+{
+ using boost::spirit::karma::generate;
+
+ char buffer[256];
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+
+ generate(p, double3, 12345.12345);
+
+ *p = '\0';
+ }
+
+ std::cout << "karma: " << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_karma_rule()
+{
+ using boost::spirit::karma::generate;
+
+ boost::spirit::karma::rule<char*, double()> r;
+
+ char buffer[256];
+ r %= double3;
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+
+ generate(p, r, 12345.12345);
+
+ *p = '\0';
+ }
+
+ std::cout << "karma (rule): " << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_karma_direct()
+{
+ using boost::spirit::karma::generate;
+ using boost::spirit::karma::real_inserter;
+
+ typedef real_inserter<double, double3_policy<double> > inserter;
+
+ char buffer[256];
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+
+ inserter::call(p, 12345.12345, double3_policy<double>());
+
+ *p = '\0';
+ }
+
+ std::cout << "karma (direct): " << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_karma_string()
+{
+ using boost::spirit::karma::generate;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ generated.clear();
+
+ generate(sink, double3, 12345.12345);
+ }
+
+ std::cout << "karma (string): " << t.elapsed() << std::endl;
+// std::cout << generated << std::endl;
+}
+
+// Boost.Format
+void format_performance_boost_format()
+{
+ std::stringstream strm;
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ strm.str("");
+ strm << boost::format("%f") % 12345.12345;
+ }
+
+ std::cout << "format: " << t.elapsed() << std::endl;
+// std::cout << strm.str() << std::endl;
+}
+
+void format_performance_printf()
+{
+ util::high_resolution_timer t;
+
+ char buffer[256];
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ sprintf(buffer, "%f", 12345.12345);
+ }
+
+ std::cout << "printf: " << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_iostreams()
+{
+ std::stringstream strm;
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ strm.str("");
+
+ strm << 12345.12345;
+ }
+
+ std::cout << "iostreams: " << t.elapsed() << std::endl;
+// std::cout << strm.str() << std::endl;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ format_performance_printf();
+ format_performance_iostreams();
+ format_performance_boost_format();
+ format_performance_karma();
+ format_performance_karma_string();
+ format_performance_karma_rule();
+ format_performance_karma_direct();
+ return 0;
+}
+

Added: trunk/libs/spirit/example/karma/format_performance.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/karma/format_performance.cpp 2009-07-14 15:47:03 EDT (Tue, 14 Jul 2009)
@@ -0,0 +1,165 @@
+// Copyright (c) 2002-2009 Joel Hartmut Kaiser
+// Copyright (c) 2002-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)
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/format.hpp>
+
+#include <iostream>
+
+#include "high_resolution_timer.hpp"
+
+#define NUMITERATIONS 100000
+
+///////////////////////////////////////////////////////////////////////////////
+// policy for real_generator, which forces to output trailing zeros in the
+// fractional part
+template <typename T>
+struct double3 : boost::spirit::karma::real_policies<T>
+{
+ // we want to generate up to 3 fractional digits
+ static unsigned int precision(T) { return 3; }
+};
+
+typedef boost::spirit::karma::real_generator<double, double3<double> >
+ double3_type;
+double3_type const double3 = double3_type();
+
+void format_performance_karma()
+{
+ using boost::spirit::karma::left_align;
+ using boost::spirit::karma::generate;
+
+ char buffer[256];
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+
+ generate(p
+ , '[' << left_align(14)[double3] << left_align(14)[double3] << ']'
+ , 12345.12345, 12345.12345);
+
+ *p = '\0';
+ }
+
+ std::cout << "karma: " << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_karma_rule()
+{
+ using boost::spirit::karma::left_align;
+ using boost::spirit::karma::generate;
+
+ typedef boost::fusion::vector<double, double> rtype;
+ boost::spirit::karma::rule<char*, rtype()> r;
+
+ char buffer[256];
+ r %= '[' << left_align(14)[double3] << left_align(14)[double3] << ']';
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+
+ generate(p, r, 12345.12345, 12345.12345);
+
+ *p = '\0';
+ }
+
+ std::cout << "karma (rule): " << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_karma_string()
+{
+ using boost::spirit::karma::left_align;
+ using boost::spirit::karma::generate;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ generated.clear();
+
+ generate(sink
+ , '[' << left_align(14)[double3] << left_align(14)[double3] << ']'
+ , 12345.12345, 12345.12345);
+ }
+
+ std::cout << "karma (string): " << t.elapsed() << std::endl;
+// std::cout << generated << std::endl;
+}
+
+// Boost.Format
+void format_performance_boost_format()
+{
+ std::stringstream strm;
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ strm.str("");
+ strm << boost::format("[%-14.3f%-14.3f]") % 12345.12345 % 12345.12345;
+ }
+
+ std::cout << "format: " << t.elapsed() << std::endl;
+// std::cout << strm.str() << std::endl;
+}
+
+void format_performance_printf()
+{
+ util::high_resolution_timer t;
+
+ char buffer[256];
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ sprintf(buffer, "[%-14.3f%-14.3f]", 12345.12345, 12345.12345);
+ }
+
+ std::cout << "printf: " << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_iostreams()
+{
+ std::stringstream strm;
+
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ strm.str("");
+
+ strm << '['
+ << std::setiosflags(std::ios::fixed)
+ << std::left
+ << std::setprecision(3)
+ << std::setw(14)
+ << 12345.12345
+ << std::setw(14)
+ << 12345.12345
+ << ']';
+ }
+
+ std::cout << "iostreams: " << t.elapsed() << std::endl;
+// std::cout << strm.str() << std::endl;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+// format_performance_printf();
+// format_performance_iostreams();
+// format_performance_boost_format();
+ format_performance_karma();
+// format_performance_karma_string();
+// format_performance_karma_rule();
+ return 0;
+}
+

Added: trunk/libs/spirit/example/karma/high_resolution_timer.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/karma/high_resolution_timer.hpp 2009-07-14 15:47:03 EDT (Tue, 14 Jul 2009)
@@ -0,0 +1,320 @@
+// Copyright (c) 2005-2009 Hartmut Kaiser
+//
+// 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)
+
+#if !defined(HIGH_RESOLUTION_TIMER_MAR_24_2008_1222PM)
+#define HIGH_RESOLUTION_TIMER_MAR_24_2008_1222PM
+
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+
+#if defined(BOOST_HAS_UNISTD_H)
+#include <unistd.h>
+#endif
+#include <time.h>
+
+#if defined(BOOST_WINDOWS)
+
+#include <stdexcept>
+#include <limits>
+#include <windows.h>
+
+namespace util
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // high_resolution_timer
+ // A timer object measures elapsed time.
+ // CAUTION: Windows only!
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ class high_resolution_timer
+ {
+ public:
+ high_resolution_timer()
+ {
+ restart();
+ }
+
+ high_resolution_timer(double t)
+ {
+ LARGE_INTEGER frequency;
+ if (!QueryPerformanceFrequency(&frequency))
+ boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
+
+ start_time.QuadPart = (LONGLONG)(t * frequency.QuadPart);
+ }
+
+ high_resolution_timer(high_resolution_timer const& rhs)
+ : start_time(rhs.start_time)
+ {
+ }
+
+ static double now()
+ {
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+
+ FILETIME ft;
+ SystemTimeToFileTime(&st, &ft);
+
+ LARGE_INTEGER now;
+ now.LowPart = ft.dwLowDateTime;
+ now.HighPart = ft.dwHighDateTime;
+
+ // FileTime is in 100ns increments, result needs to be in [s]
+ return now.QuadPart * 1e-7;
+ }
+
+ void restart()
+ {
+ if (!QueryPerformanceCounter(&start_time))
+ boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
+ }
+ double elapsed() const // return elapsed time in seconds
+ {
+ LARGE_INTEGER now;
+ if (!QueryPerformanceCounter(&now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+
+ LARGE_INTEGER frequency;
+ if (!QueryPerformanceFrequency(&frequency))
+ boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
+
+ return double(now.QuadPart - start_time.QuadPart) / frequency.QuadPart;
+ }
+
+ double elapsed_max() const // return estimated maximum value for elapsed()
+ {
+ LARGE_INTEGER frequency;
+ if (!QueryPerformanceFrequency(&frequency))
+ boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
+
+ return double((std::numeric_limits<LONGLONG>::max)() - start_time.QuadPart) /
+ double(frequency.QuadPart);
+ }
+
+ double elapsed_min() const // return minimum value for elapsed()
+ {
+ LARGE_INTEGER frequency;
+ if (!QueryPerformanceFrequency(&frequency))
+ boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
+
+ return 1.0 / frequency.QuadPart;
+ }
+
+ private:
+ LARGE_INTEGER start_time;
+ };
+
+} // namespace util
+
+#elif defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(_POSIX_THREAD_CPUTIME)
+
+#if _POSIX_THREAD_CPUTIME > 0 // timer always supported
+
+namespace util
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // high_resolution_timer
+ // A timer object measures elapsed time.
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ class high_resolution_timer
+ {
+ public:
+ high_resolution_timer()
+ {
+ start_time.tv_sec = 0;
+ start_time.tv_nsec = 0;
+
+ restart();
+ }
+
+ high_resolution_timer(double t)
+ {
+ start_time.tv_sec = time_t(t);
+ start_time.tv_nsec = (t - start_time.tv_sec) * 1e9;
+ }
+
+ high_resolution_timer(high_resolution_timer const& rhs)
+ : start_time(rhs.start_time)
+ {
+ }
+
+ static double now()
+ {
+ timespec now;
+ if (-1 == clock_gettime(CLOCK_REALTIME, &now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+ return double(now.tv_sec) + double(now.tv_nsec) * 1e-9;
+ }
+
+ void restart()
+ {
+ if (-1 == clock_gettime(CLOCK_REALTIME, &start_time))
+ boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
+ }
+ double elapsed() const // return elapsed time in seconds
+ {
+ timespec now;
+ if (-1 == clock_gettime(CLOCK_REALTIME, &now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+
+ if (now.tv_sec == start_time.tv_sec)
+ return double(now.tv_nsec - start_time.tv_nsec) * 1e-9;
+
+ return double(now.tv_sec - start_time.tv_sec) +
+ (double(now.tv_nsec - start_time.tv_nsec) * 1e-9);
+ }
+
+ double elapsed_max() const // return estimated maximum value for elapsed()
+ {
+ return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec);
+ }
+
+ double elapsed_min() const // return minimum value for elapsed()
+ {
+ timespec resolution;
+ if (-1 == clock_getres(CLOCK_REALTIME, &resolution))
+ boost::throw_exception(std::runtime_error("Couldn't get resolution"));
+ return double(resolution.tv_sec + resolution.tv_nsec * 1e-9);
+ }
+
+ private:
+ timespec start_time;
+ };
+
+} // namespace util
+
+#else // _POSIX_THREAD_CPUTIME > 0
+
+#include <boost/timer.hpp>
+
+// availability of high performance timers must be checked at runtime
+namespace util
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // high_resolution_timer
+ // A timer object measures elapsed time.
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ class high_resolution_timer
+ {
+ public:
+ high_resolution_timer()
+ : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0)
+ {
+ if (!use_backup) {
+ start_time.tv_sec = 0;
+ start_time.tv_nsec = 0;
+ }
+ restart();
+ }
+
+ high_resolution_timer(double t)
+ : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0)
+ {
+ if (!use_backup) {
+ start_time.tv_sec = time_t(t);
+ start_time.tv_nsec = (t - start_time.tv_sec) * 1e9;
+ }
+ }
+
+ high_resolution_timer(high_resolution_timer const& rhs)
+ : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0),
+ start_time(rhs.start_time)
+ {
+ }
+
+ static double now()
+ {
+ if (sysconf(_SC_THREAD_CPUTIME) <= 0)
+ return double(std::clock());
+
+ timespec now;
+ if (-1 == clock_gettime(CLOCK_REALTIME, &now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+ return double(now.tv_sec) + double(now.tv_nsec) * 1e-9;
+ }
+
+ void restart()
+ {
+ if (use_backup)
+ start_time_backup.restart();
+ else if (-1 == clock_gettime(CLOCK_REALTIME, &start_time))
+ boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
+ }
+ double elapsed() const // return elapsed time in seconds
+ {
+ if (use_backup)
+ return start_time_backup.elapsed();
+
+ timespec now;
+ if (-1 == clock_gettime(CLOCK_REALTIME, &now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+
+ if (now.tv_sec == start_time.tv_sec)
+ return double(now.tv_nsec - start_time.tv_nsec) * 1e-9;
+
+ return double(now.tv_sec - start_time.tv_sec) +
+ (double(now.tv_nsec - start_time.tv_nsec) * 1e-9);
+ }
+
+ double elapsed_max() const // return estimated maximum value for elapsed()
+ {
+ if (use_backup)
+ start_time_backup.elapsed_max();
+
+ return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec);
+ }
+
+ double elapsed_min() const // return minimum value for elapsed()
+ {
+ if (use_backup)
+ start_time_backup.elapsed_min();
+
+ timespec resolution;
+ if (-1 == clock_getres(CLOCK_REALTIME, &resolution))
+ boost::throw_exception(std::runtime_error("Couldn't get resolution"));
+ return double(resolution.tv_sec + resolution.tv_nsec * 1e-9);
+ }
+
+ private:
+ bool use_backup;
+ timespec start_time;
+ boost::timer start_time_backup;
+ };
+
+} // namespace util
+
+#endif // _POSIX_THREAD_CPUTIME > 0
+
+#else // !defined(BOOST_WINDOWS) && (!defined(_POSIX_TIMERS)
+ // || _POSIX_TIMERS <= 0
+ // || !defined(_POSIX_THREAD_CPUTIME)
+ // || _POSIX_THREAD_CPUTIME <= 0)
+
+// For platforms other than Windows or Linux, simply fall back to boost::timer
+#include <boost/timer.hpp>
+
+namespace util
+{
+ struct high_resolution_timer
+ : boost::timer
+ {
+ static double now()
+ {
+ return double(std::clock());
+ }
+ };
+}
+
+#endif
+
+#endif
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk