$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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  
+