Boost logo

Boost :

Subject: Re: [boost] [xpressive] Performance Tuning?
From: OvermindDL1 (overminddl1_at_[hidden])
Date: 2009-07-15 08:51:53


Okay, I made a Spirit version and I am wanting to compare times,
however no one has posted any compilable code here yet, nor test
cases, nor anything I can use, so I am just guessing that it is
correct since I have no data to run through it.

Since none of the above code actually compiles as-is, and I do not
feel like dealing with incomplete examples, here are the times on my
computer using the code below.
When parsing "42", this would be an example of the fastest case:

        char const *s1 = "42", *e1 = s1 + std::strlen(s1);
        boost::long_long_type result;
        size_t counter = 1000000;
        while(counter--) parse_price_spirit(s1, e1, result);

This executed in no real measurable time... might have been optimized
out, let me check the assembly, nope, very much not optimized out, the
loop is run, the function is not inlined, and it is indeed called
1000000 times.

Okay, running this with 10000000 (7 zero's, 10 million loops, 9
million extra then the above tests) instead takes about ~1.5 seconds.

Now running the test with "42.5", which should be the *slowest*
possible case for the code I wrote, with 1000000 (6 zero's, one
million) it took still no noticeable time. With 10000000 (7 zero's,
10 million) iterations it took roughly about ~1.5 seconds again.

I would really love to have the same test cases and scaffolds that
everyone else is using so I can do some real timings though.

And yes, my parser, for a string it returns -> value:
"42" -> 6720000 (42*160000)
"42 1/2" -> 6800000 (42*16000 + (1*16000)/2)
"42.5" -> 6800000 (42*16000 + floor(160000.0*0.5 + 0.5))
"4.2e1" -> 6720000 (42*160000)

This is comparing with someone elses above timings, have no clue of
his compile type, hardware, anything, and he did not post his code,
but these are the times that he posted:
> 1) The original code
> 2) Static const regexes
> 3) Static const regexes with reused match results objects
>
> I ran each config for 1000000 iterations and got roughly
> these numbers:
>
> 1) ~950 sec
> 2) ~45 sec
> 3) ~9 sec

All of the above I did was using MSVC 2k5 in release mode in Windows
XP on an old AMD Athlon 1.8ghz Opteron processor. If anyone can give
me the above code (his original version and the xpressive version) as
compilable files so I do not need to deal with anything, then I can
run a proper, full, and millisecond detailed timings. Based on my
above timings, either my ancient 1.8ghz computer is rather massively
faster then his computer, or Spirit2.1 is much faster then both
xpressive and the original code (which someone else said above, the
optimized xpressive takes about 20% or so longer I think?).

The code, I whipped it up quickly, not pretty, just getting it
functional since the guidelines are not very well set, do note, this
is not how I normally make my Spirit parsers, but if someone gives me
the source of the other things, then I will do this one properly once
I confirm that this parses what needs to be parsed (to compile this,
make sure you are running Boost Trunk!):
#include <boost/tr1/cmath.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

BOOST_STATIC_ASSERT(sizeof(boost::long_long_type) == 8);

boost::long_long_type tmpResult;
inline void dotNumber(const double a1)
{
        tmpResult += static_cast<boost::long_long_type>(std::floor(160000.0*a1 + 0.5));
}

template <typename Iterator>
bool parse_price_spirit(Iterator first, Iterator last, boost::long_long_type &c)
{
        using boost::spirit::qi::double_;
        using boost::spirit::qi::_1;
        using boost::spirit::qi::_2;
        using boost::spirit::qi::phrase_parse;
        using boost::spirit::qi::lexeme;
        using boost::spirit::qi::lit;
        using boost::spirit::ascii::space;
        using boost::spirit::ascii::blank;
        using boost::phoenix::ref;
        using boost::spirit::long_long;
        using boost::long_long_type;

        bool r = phrase_parse(first, last,

                        // Begin grammar
                        // I did not put this in a grammar class because I am being
                        // lazy, plenty of examples of that anyway, and no, it is not
                        // faster here, it is the same speed whether inline here or in
                        // a grammar class.
                        ( (long_long[ref(tmpResult)=(_1*160000)] >> !lit('.') >>
-(long_long >> '/' >> long_long)[ref(tmpResult)+=160000*_1/_2])
                        | double_[&dotNumber]
                        )
                        // End grammar

                ,blank);

        if (!r || first != last) // fail if we did not get a full match
                return false;

        c = tmpResult;

        return r;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk