[boost] [xpressive] Performance Tuning?

220 views
Skip to first unread message

Stewart, Robert

unread,
Jun 30, 2009, 5:04:00 PM6/30/09
to bo...@lists.boost.org
I was experimenting with Xpressive to see how it would compare with some custom, string-based numeric input parsing. The Xpressive code is over 175X slower than the custom code. Have I done anything to make it really slow? Can it be made faster? I have included the Xpressive code and the performance testing code below for your study. Can you spot anything I've done wrong?

(BTW, I tried using Spirit.Qi for this -- with Boost 1.37 -- but never could get things to compile. I gave up and decided I'd wait until I can use a newer release before I fight that fight again. :-} )

FYI: bar::numeric_cast winds up calling strtod(), strtol(), etc. It is semantically equivalent to lexical_cast.

#include <boost/xpressive/xpressive_static.hpp>
#include <boost/xpressive/regex_actions.hpp>

namespace foo
{
namespace op
{
template <class T>
struct numeric_cast
{
typedef T result_type;

template <class Value>
T
operator ()(Value const & _value) const
{
return bar::numeric_cast<T>(_value);
}
};
}

struct direct_impl
{
typedef int64_t result_type;

template <class Value>
int64_t
operator ()(Value const & _value) const
{
int64_t result(bar::numeric_cast<int64_t>(_value));
result *= 160000;
return result;
}
};

struct to_price_impl
{
typedef int64_t result_type;

template <class Value>
int64_t
operator ()(Value const & _value) const
{
int64_t result(0);
if (_value)
{
double const value(bar::numeric_cast<double>(_value));
result = static_cast<int64_t>(
std::floor(160000.0 * value + 0.5));
}
return result;
}

template <class Value>
int64_t
operator ()(Value const & _numerator, Value const & _denominator) const
{
unsigned const numerator(bar::numeric_cast<unsigned>(_numerator));
unsigned const denominator(bar::numeric_cast<unsigned>(_denominator));
double const fraction((160000.0 * numerator) / denominator);
return static_cast<int64_t>(std::floor(fraction + 0.5));
}

template <class Value>
int64_t
operator ()(Value const & _whole, double const _fraction) const
{
int const whole(bar::numeric_cast<int>(_whole));
double const value(160000.0 * whole + _fraction);
return static_cast<int64_t>(std::floor(value + 0.5));
}
};

int64_t
parse(std::string const & _value);

boost::xpressive::function<direct_impl>::type const direct = {{}};
boost::xpressive::function<to_price_impl>::type const to_price = {{}};
BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE(
1
, numeric_cast
, boost::proto::default_domain
, (boost::proto::tag::function)
, ((op::numeric_cast)(typename))
)
}

int64_t
foo::parse(std::string const & _value)
{
using namespace boost::xpressive;

if (_value.empty())
{
return 0;
}
int64_t result;
bool negative(false);
sregex zero = as_xpr('0');
sregex sign =
as_xpr('-') [ ref(negative) = true ]
| as_xpr('+'); // ignore
// ignore leading zeroes to avoid octal parsing
sregex fraction =
(
!zero >> (s1= +_d) >> !blank >> '/' >> !blank >> !zero >> (s2= +_d)
) [ ref(result) = to_price(s1, s2) ];
sregex real =
(
*_d >> '.' >> *_d >> !((set= 'E', 'e', 'G', 'g') >> +_d)
) [ ref(result) = to_price(_) ];
// ignore leading zeroes to avoid octal parsing
sregex whole_number =
(
!zero >> (s1= +_d) >> +blank >> fraction
) [ ref(result) = to_price(s1, ref(result)) ];
// ignore leading zeroes to avoid octal parsing
sregex integer =
(
!zero >> (s1= +_d)
) [ ref(result) = direct(s1) ];
sregex price =
*blank
>> !sign
>> (real | whole_number | fraction | integer)
>> *space;
smatch match;
if (!regex_match(_value.begin(), _value.end(), match, price))
{
throw price_parsing_failed(_value);
}
if (negative)
{
result = -result;
}
return result;
}

void
test_performance()
{
Timer timer;
std::string const input("1234.5678e10");
int64_t total(0);
foo::parse(input); // prime the cache
timer.start();
for (int i(0); i < 10000000; ++i)
{
int64_t price(foo::parse(input));
price += i;
total += price;
}
timer.stop();
std::cout << timer.elapsed() << "s elapsed (total = " << total ')'
<< std::endl;
}

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Eric Niebler

unread,
Jun 30, 2009, 5:36:11 PM6/30/09
to bo...@lists.boost.org

Stewart, Robert wrote:
> I was experimenting with Xpressive to see how it would compare with
> some custom, string-based numeric input parsing. The Xpressive code
> is over 175X slower than the custom code. Have I done anything to
> make it really slow? Can it be made faster?
<snip>

Where is the code against which you are benchmarking?

From looking at the code, I can see a few areas for improvement. With
each call to parse(), you construct and discard a match_results object.
For optimal performance, you should reuse the match_results object to
avoid extra memory allocation. Also, many of the quantifiers in your
grammar do not require backtracking, so you could use keep() to turn
backtracking off selectively.

That's all I have for now.

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Stewart, Robert

unread,
Jul 1, 2009, 9:13:27 AM7/1/09
to bo...@lists.boost.org
Eric Niebler wrote:
> Stewart, Robert wrote:
> > I was experimenting with Xpressive to see how it would
> > compare with some custom, string-based numeric input parsing.
> > The Xpressive code is over 175X slower than the custom code.
> > Have I done anything to make it really slow? Can it be made
> > faster?
> <snip>
>
> Where is the code against which you are benchmarking?

See below. As you'll see, it isn't nearly as maintainable or clear, but the wide performance difference certainly favors it.

> From looking at the code, I can see a few areas for
> improvement. With each call to parse(), you construct and
> discard a match_results object. For optimal performance, you
> should reuse the match_results object to avoid extra memory
> allocation. Also, many of the quantifiers in your grammar do
> not require backtracking, so you could use keep() to turn
> backtracking off selectively.

The function is called in a one-off fashion that wouldn't permit keeping the match_results object, unfortunately. (A function local static would suffice but then the function wouldn't be thread safe.)

I'm not certain I understand where to apply keep(), but I'll have a go at it.

_______________________
FYI: bar::to_number() calls strtod(), strtol(), etc.

template <class T>
T
foo::extract(char const * & _input, char const * const _description,
std::string const & _value)
{
T result;
if (!bar::to_number(result, _input, &_input, 10))
{
raise_extract_failed(_description, _value);
}
return result;
}

inline int64_t
foo::round(const double _value)
{
return static_cast<int64_t>(std::floor(_value + 0.5));
}

int64_t
foo::parse(std::string const & _value)
{

if (_value.empty())
{
return 0;
}
size_t offset(_value.find_first_not_of("-+0123456789eE ./"));
const bool invalid(std::string::npos != offset);
if (invalid)
{
raise_parsing_failed(_value);
}
const char * const input(_value.c_str());
const char * const last(input + _value.length());
const char * end(input);
int64_t result;
(void)bar::to_number(result, end, &end, 10);
const bool floating_point('.' == *end);
if (floating_point)
{
end = input;
const double value(extract<double>(end, "input", _value));
const bool negative(0.0 > value);
double multiple(value * 160000.0);
if (negative)
{
multiple = -multiple;
}
result = round(multiple);


if (negative)
{
result = -result;
}
}

else // not floating point
{
result *= 160000;
if (end != last)
{
offset = _value.find_first_of('/', end - input);
const bool is_fraction(std::string::npos != offset);
if (is_fraction)
{
const bool negative(0 > result);


if (negative)
{
result = -result;
}

offset = _value.find_last_of(' ', offset);
const bool is_mixed_number(std::string::npos != offset);
if (is_mixed_number)
{
const unsigned numerator(
extract<unsigned>(end, "numerator", _value));
end += 1; // skip the slash
const unsigned denominator(
extract<unsigned>(end, "denominator", _value));
const double fraction((160000.0 * numerator) / denominator);
result = round(result + fraction);
}
else
{
end += 1; // skip the slash
const unsigned denominator(
extract<unsigned>(end, "denominator", _value));
const double fraction(result / denominator);
result = round(fraction);


}
if (negative)
{
result = -result;
}
}
}
}
return result;
}

_____


Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Dave Jenkins

unread,
Jul 1, 2009, 2:20:34 PM7/1/09
to bo...@lists.boost.org

"Stewart, Robert" <Robert....@sig.com> wrote in message
news:DF2E67F3D097004694C84...@msgbal516.ds.susq.com...

>I was experimenting with Xpressive to see how it would compare with some
>custom, string-based numeric input parsing. The Xpressive code is over
>175X slower than the custom code.

Each call to parse() is constructing the sregex variables. If you make them
static or move them out of the loop, it should help a lot.

Regards,
Dave Jenkins

Stewart, Robert

unread,
Jul 1, 2009, 2:23:40 PM7/1/09
to bo...@lists.boost.org
Dave Jenkins wrote:
> "Stewart, Robert" <Robert....@sig.com> wrote in message
> news:DF2E67F3D097004694C84...@msgbal516.ds.s
> usq.com...
> >I was experimenting with Xpressive to see how it would
> compare with some
> >custom, string-based numeric input parsing. The Xpressive
> code is over
> >175X slower than the custom code.
>
> Each call to parse() is constructing the sregex variables.
> If you make them
> static or move them out of the loop, it should help a lot.

Thanks, but see my reply to Eric's. While that would help with the benchmark performance, the nature of the function I'm testing means I can't do that otherwise.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Dave Jenkins

unread,
Jul 1, 2009, 2:40:02 PM7/1/09
to bo...@lists.boost.org
>> Each call to parse() is constructing the sregex variables.
>> If you make them
>> static or move them out of the loop, it should help a lot.
>
> Thanks, but see my reply to Eric's. While that would help with the
> benchmark performance, the nature of the function I'm testing means I
> can't do that otherwise.

How about making them static const? That should be thread safe.

Stewart, Robert

unread,
Jul 1, 2009, 3:15:21 PM7/1/09
to bo...@lists.boost.org
Dave Jenkins wrote:
>
> >> Each call to parse() is constructing the sregex variables.
> >> If you make them static or move them out of the loop, it
> >> should help a lot.
> >
> > Thanks, but see my reply to Eric's. While that would help
> > with the benchmark performance, the nature of the function
> > I'm testing means I can't do that otherwise.
>
> How about making them static const? That should be thread safe.

I'm sorry, I read your original suggestion as being the same as Eric's: reuse the match_results. Unfortunately, the semantic actions reference local variables, so I don't think I can make the sregex's static (please correct me if I'm wrong, but I can't see how multiple parallel invocations of the function could reference separate stack variables from static sregex's). I did make the sregex's const; that appears to have improved performance a bit.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Eric Niebler

unread,
Jul 1, 2009, 3:20:30 PM7/1/09
to bo...@lists.boost.org
Stewart, Robert wrote:
> Dave Jenkins wrote:
>> "Stewart, Robert" wrote:
>>> I was experimenting with Xpressive to see how it would compare
>>> with some custom, string-based numeric input parsing. The
>>> Xpressive code is over 175X slower than the custom code.
>>
>> Each call to parse() is constructing the sregex variables. If you
>> make them static or move them out of the loop, it should help a
>> lot.
>
> Thanks, but see my reply to Eric's. While that would help with the
> benchmark performance, the nature of the function I'm testing means I
> can't do that otherwise.

Really what you're saying is: "I can't/don't want to use xpressive in
the ways that are *documented* to make it perform well. Why is it slow?"
You already have your answer.

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Eric Niebler

unread,
Jul 1, 2009, 3:23:02 PM7/1/09
to bo...@lists.boost.org
Stewart, Robert wrote:
> Dave Jenkins wrote:
>>>> Each call to parse() is constructing the sregex variables.
>>>> If you make them static or move them out of the loop, it
>>>> should help a lot.
>>> Thanks, but see my reply to Eric's. While that would help
>>> with the benchmark performance, the nature of the function
>>> I'm testing means I can't do that otherwise.
>> How about making them static const? That should be thread safe.
>
> I'm sorry, I read your original suggestion as being the same as Eric's: reuse the match_results. Unfortunately, the semantic actions reference local variables, so I don't think I can make the sregex's static (please correct me if I'm wrong, but I can't see how multiple parallel invocations of the function could reference separate stack variables from static sregex's). I did make the sregex's const; that appears to have improved performance a bit.

You can still make the regex objects static const and use placeholders
in the semantic actions. See the following section:

http://www.boost.org/doc/libs/1_39_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.semantic_actions_and_user_defined_assertions.referring_to_non_local_variables

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Stewart, Robert

unread,
Jul 1, 2009, 3:26:55 PM7/1/09
to bo...@lists.boost.org
Eric Niebler wrote:
>
> Really what you're saying is: "I can't/don't want to use
> xpressive in the ways that are *documented* to make it perform
> well. Why is it slow?" You already have your answer.

So be it. I was just hoping I had done something silly and could rearrange things to improve the performance.

Thanks for your attention.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert

unread,
Jul 1, 2009, 3:39:06 PM7/1/09
to bo...@lists.boost.org
Eric Niebler wrote:
> Stewart, Robert wrote:
> > Dave Jenkins wrote:
> >>>> Each call to parse() is constructing the sregex variables.
[snip]

> >> How about making them static const? That should be thread safe.
>
> You can still make the regex objects static const and use
> placeholders in the semantic actions. See the following
> section:
>
> http://www.boost.org/doc/libs/1_39_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.semantic_actions_and_user_defined_assertions.referring_to_non_local_variables

I forgot about that section. Thanks for the pointer.

Whoa! The performance just shot up to a mere 6X the custom code (from 175X). That might well be fast enough to keep the Xpressive version because of its readability!

Thanks Eric!

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Dave Jenkins

unread,
Jul 1, 2009, 4:50:37 PM7/1/09
to bo...@lists.boost.org
> Whoa! The performance just shot up to a mere 6X the custom code (from
> 175X). That might well be fast enough to keep the Xpressive version
> because of its readability!

Can you create thread-local match_results objects and reuse them? If so, I
think you'll see parsing dwindle to almost nothing and your semantic actions
will account for the bulk of the time spent.

Regards,
Dave Jenkins

Eric Niebler

unread,
Jul 1, 2009, 6:09:37 PM7/1/09
to bo...@lists.boost.org
Dave Jenkins wrote:

> Robert Stuart wrote:
>> Whoa! The performance just shot up to a mere 6X the custom code (from
>> 175X). That might well be fast enough to keep the Xpressive version
>> because of its readability!
>
> Can you create thread-local match_results objects and reuse them? If
> so, I think you'll see parsing dwindle to almost nothing and your
> semantic actions will account for the bulk of the time spent.

Dave, thanks for spotting the obvious perf problem I missed. I can
confirm that reusing the match results object largely eliminates the
remaining performance problem. I tried 3 different scenarios:

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

So reusing the match results object (3) results in a 5x speedup over
just using static const regexes (2). That almost completely erases any
performance advantage of the hand-crafted parsing code.

I'll also point out this section of the docs:
http://www.boost.org/doc/libs/1_39_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.tips_n_tricks

Both of the above optimizations (reuse regexes and match_results
objects) are recommended there.

Thanks,

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Matthew Chambers

unread,
Jul 1, 2009, 5:23:35 PM7/1/09
to bo...@lists.boost.org
Why is Xpressive more readable than using lexical_cast or your
numeric_cast? I've implemented specializations of lexical_cast for
string->numeric conversions using strto[ld]. It is a vast speed
improvement of course, and since those specializations are hidden away
in a header, readability is the same as with normal lexical_casts. Maybe
I'm misunderstanding your use case? Do you not know ahead of time what
the type of the number will be?

-Matt

Stewart, Robert

unread,
Jul 2, 2009, 8:17:10 AM7/2/09
to bo...@lists.boost.org
Eric Niebler wrote:
> Dave Jenkins wrote:

> > Robert Stewart wrote:
> >> Whoa! The performance just shot up to a mere 6X the custom
> >> code (from 175X). That might well be fast enough to keep
> >> the Xpressive version because of its readability!
> >
> > Can you create thread-local match_results objects and reuse
> > them? If so, I think you'll see parsing dwindle to almost
> > nothing and your semantic actions will account for the bulk
> > of the time spent.

At Dave's suggestion, I tried that.

> Dave, thanks for spotting the obvious perf problem I missed. I can
> confirm that reusing the match results object largely eliminates the
> remaining performance problem. I tried 3 different scenarios:
>
> 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
>
> So reusing the match results object (3) results in a 5x speedup
> over just using static const regexes (2). That almost
> completely erases any performance advantage of the hand-crafted
> parsing code.

Unfortunately, my results don't bear that out with the added overhead of locating the smatch via thread local storage. I see no difference between default constructing an smatch each time and reusing an instance from TLS.

> I'll also point out this section of the docs:
> http://www.boost.org/doc/libs/1_39_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.tips_n_tricks
>
> Both of the above optimizations (reuse regexes and
> match_results objects) are recommended there.

I read through some of those quickly upon an initial read through the documentation. I chose static regexes because I understood them to be faster. I did not reuse the match_results<> because they aren't thread safe. Dave's TLS suggestion hadn't occurred to me to reconcile the competing forces of reuse and no thread safety, of course.

Upon rereading, I see that you note that reusing a static regex improves performance, but I'd forgotten it by the time I needed the information. May I suggest a "Performance Tuning" section that discusses such things apart from common pitfalls, etc. and stands out better in the TOC? I didn't expect to find such information in a "Tips and Tricks" section, and forgotten that I had seen it when it was wanted.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert

unread,
Jul 2, 2009, 8:21:14 AM7/2/09
to bo...@lists.boost.org
Matthew Chambers wrote:
>
> Why is Xpressive more readable than using lexical_cast or your
> numeric_cast? I've implemented specializations of lexical_cast
> for string->numeric conversions using strto[ld]. It is a vast
> speed improvement of course, and since those specializations
> are hidden away in a header, readability is the same as with
> normal lexical_casts. Maybe I'm misunderstanding your use case?
> Do you not know ahead of time what the type of the number will
> be?

If you'll have a look at my first post in this thread, you'll see the Xpressive code and the grammar I've implemented. A later post shows the string-based parsing logic that uses string-to-number conversions similar to what you suggest. (Indeed, the Xpressive semantic actions involve the same sorts of conversions.) As you'll see, the code must parse whole numbers, fractions, mixed numbers, and real numbers.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Dave Jenkins

unread,
Jul 2, 2009, 10:01:05 AM7/2/09
to bo...@lists.boost.org

"Stewart, Robert" <Robert....@sig.com> wrote in message
news:DF2E67F3D097004694C84...@msgbal516.ds.susq.com...
> Unfortunately, my results don't bear that out with the added overhead of
> locating the smatch via thread local storage. I see no difference between
> default constructing an smatch each time and reusing an instance from TLS.
>

It's disappointing that locating a match_results object in thread-local
storage takes approximately the same amount of time as default constructing
a new one. I had hoped for better.

Anyway, if you don't mind spending a little more time on this, I'd be
interested in seeing a breakdown of the amount of time spent on (1) locating
the match_results object in TLS, (2) parsing, and (3) semantic actions.

You could determine (1) by changing match_results to static (even though
this won't work in your actual case) and see what the time difference is.
Then if you comment out the semantic actions, you can determine the split
between parsing and semantic actions.

In any case, thanks for supplying a interesting test case of Xpressive in a
multi-threaded environment.

Dave Jenkins

Stewart, Robert

unread,
Jul 6, 2009, 4:27:21 PM7/6/09
to bo...@lists.boost.org
Dave Jenkins wrote:
> "Stewart, Robert" <Robert....@sig.com> wrote in message
> news:DF2E67F3D097004694C84...@msgbal516.ds.susq.com...
>
> > Unfortunately, my results don't bear that out with the added
> > overhead of locating the smatch via thread local storage. I
> > see no difference between default constructing an smatch each
> > time and reusing an instance from TLS.
>
> It's disappointing that locating a match_results object in
> thread-local storage takes approximately the same amount of
> time as default constructing a new one. I had hoped for
> better.

Your hopes were justified: I just noticed that while my TLS accessor returns a reference to the smatch, I saved it to a copy rather than a reference where I was using it. Correcting that mistake shows the Xpressive code taking around 1.5X the time used by the custom code.

I've seen added more test cases and updated the custom code and must now correct some things in the Xpressive code to handle all of the same cases before I can do any more measurements.

> Anyway, if you don't mind spending a little more time on this,
> I'd be interested in seeing a breakdown of the amount of time
> spent on (1) locating the match_results object in TLS, (2)
> parsing, and (3) semantic actions.

With TLS, a straightforward performance test required about 68s, whereas with a function local static, it required about 65s.

Keeping the static smatch and omitting the semantic actions changed the time to about 40s.

>From that, one can conclude that the matching takes about 40s, the semantic actions add 25s, and the TLS lookups add an additional 3s, in a loop of 100,000,000 iterations.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Eric Niebler

unread,
Jul 6, 2009, 6:56:55 PM7/6/09
to bo...@lists.boost.org
Stewart, Robert wrote:
> Dave Jenkins wrote:
>>
>> It's disappointing that locating a match_results object in
>> thread-local storage takes approximately the same amount of time as
>> default constructing a new one. I had hoped for better.
>
> I just noticed that while my TLS accessor
> returns a reference to the smatch, I saved it to a copy rather than a
> reference where I was using it. Correcting that mistake shows the
> Xpressive code taking around 1.5X the time used by the custom code.

That's much better than 175X slower!

> I've seen added more test cases and updated the custom code and must
> now correct some things in the Xpressive code to handle all of the
> same cases before I can do any more measurements.

At this point, most of the low hanging fruit is picked clean. If you are
hungry for even more performance, you can eliminate the nested regex
invocations by changing the definition of the regex objects from this:

static const sregex zero = as_xpr('0');

...to this:

static const BOOST_PROTO_AUTO(zero, as_xpr('0'));

Do this for all but the top-most regex (the one named "price" in your
first example). You must also #include <boost/proto/proto_typeof.hpp>.

When I do this, performance drops from 9.5s to 6.0s.

> With TLS, a straightforward performance test required about 68s,
> whereas with a function local static, it required about 65s.
>
> Keeping the static smatch and omitting the semantic actions changed
> the time to about 40s.
>
> From that, one can conclude that the matching takes about 40s, the
> semantic actions add 25s, and the TLS lookups add an additional 3s,
> in a loop of 100,000,000 iterations.

Very interesting. Thanks for the measurements.

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Thorsten Ottosen

unread,
Jul 7, 2009, 11:53:00 AM7/7/09
to bo...@lists.boost.org
Hi Robert,

It would be good if you could submit your code as a case in optimizing
expressive code.

-Thorsten

Stewart, Robert

unread,
Jul 7, 2009, 12:26:33 PM7/7/09
to bo...@lists.boost.org
Thorsten Ottosen wrote:
>
> It would be good if you could submit your code as a case in
> optimizing expressive code.

Where and how would you have me do so? I can see developing a performance tuning example from it to put in the documentation. I don't know how much of that Eric has in mind already or if he is interested in such an addition (of his own doing or mine).

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Paul Baxter

unread,
Jul 7, 2009, 5:09:00 PM7/7/09
to bo...@lists.boost.org
"Stewart, Robert" <Robert....@sig.com> wrote in message
news:DF2E67F3D097004694C84...@msgbal516.ds.susq.com...
> Thorsten Ottosen wrote:
>>
>> It would be good if you could submit your code as a case in
>> optimizing expressive code.
>
> Where and how would you have me do so? I can see developing a performance
> tuning example from it to put in the documentation. I don't know how much
> of that Eric has in mind already or if he is interested in such an
> addition (of his own doing or mine).

This has been an incredibly useful thread. Thanks to you all.

As a potential user put off in the past by concerns over abstraction
penalties with such libraries (even compile time libraries often fail to
deliver in all but simple cases), I urge Eric to embrace such an example to
illustrate just how powerful and maintainable a solution based on expressive
can be.

Eric Niebler

unread,
Jul 7, 2009, 5:43:49 PM7/7/09
to bo...@lists.boost.org
Paul Baxter wrote:

> "Stewart, Robert" wrote:
>> Thorsten Ottosen wrote:
>>>
>>> It would be good if you could submit your code as a case in
>>> optimizing expressive code.
>>
>> Where and how would you have me do so? I can see developing a
>> performance tuning example from it to put in the documentation. I
>> don't know how much of that Eric has in mind already or if he is
>> interested in such an addition (of his own doing or mine).
>
> This has been an incredibly useful thread. Thanks to you all.
>
> As a potential user put off in the past by concerns over abstraction
> penalties with such libraries (even compile time libraries often fail to
> deliver in all but simple cases), I urge Eric to embrace such an example
> to illustrate just how powerful and maintainable a solution based on
> expressive can be.

I think this is a fine idea. All these tips and tricks are already
described in a doc, but they are not described in depth from an end-user
perspective. I think a performance tuning case study would make a
valuable appendix.

Robert, can you send me the latest version of your regex grammar and
your hand-coded parser? I'll see what I can do.

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Dave Jenkins

unread,
Jul 9, 2009, 12:08:15 PM7/9/09
to bo...@lists.boost.org
From: "Stewart, Robert" <Robert....@sig.com>

> Your hopes were justified: I just noticed that while my TLS accessor
> returns a reference to the smatch, I saved it to a copy rather than a
> reference where I was using it. Correcting that mistake shows the
> Xpressive code taking around 1.5X the time used by the custom code.
>
> I've seen added more test cases and updated the custom code and must now
> correct some things in the Xpressive code to handle all of the same cases
> before I can do any more measurements.
>

Thanks for doing this work Rob. It's been a really fruitful exercise.

I had one other question on performance improvement, mostly for Eric. Could
you eliminate/minimize the need for match_results when semantic actions are
capturing the results? In Rob's code, he's not even looking at the
match_results because his semantic actions handle the data. Can you
optionally turn off the match_results capture in that case to save space and
time?

Regards,
Dave Jenkins

P.S. If I'm slow to respond, it's because I'm on vacation and internet
access is spotty.

Kim Scheibel

unread,
Jul 9, 2009, 2:05:08 PM7/9/09
to bo...@lists.boost.org
Eric Niebler wrote:

> Robert, can you send me the latest version of your regex grammar and
> your hand-coded parser? I'll see what I can do.

Actually, Rob, would you mind posting it here?

/Kim

Stewart, Robert

unread,
Jul 10, 2009, 9:32:05 AM7/10/09
to bo...@lists.boost.org
Eric Niebler wrote:
> Paul Baxter wrote:
> > "Stewart, Robert" wrote:
> >> Thorsten Ottosen wrote:
> >>>
> >>> It would be good if you could submit your code as a case in
> >>> optimizing expressive code.
> >>
> >> Where and how would you have me do so? I can see developing
> >> a performance tuning example from it to put in the
> >> documentation. I don't know how much of that Eric has in
> >> mind already or if he is interested in such an addition (of
> >> his own doing or mine).
> >
> > This has been an incredibly useful thread. Thanks to you all.
> >
> > As a potential user put off in the past by concerns over
> > abstraction penalties with such libraries (even compile time
> > libraries often fail to deliver in all but simple cases), I
> > urge Eric to embrace such an example to illustrate just how
> > powerful and maintainable a solution based on expressive can
> > be.
>
> I think this is a fine idea. All these tips and tricks are
> already described in a doc, but they are not described in depth
> from an end-user perspective. I think a performance tuning case
> study would make a valuable appendix.
>
> Robert, can you send me the latest version of your regex
> grammar and your hand-coded parser? I'll see what I can do.

Sure. I've attached both in one file, but with separate namespaces. My progression, as you can ascertain from retracing this thread, was from automatic sregexes and an automatic smatch to putting the sregexes in a namespace, which required creating placeholders, to putting the smatch into thread local storage, to using BOOST_PROTO_AUTO. That progression changed the performance of the Xpressive code from about 175X slower to less than 2X slower than the custom code. (I haven't measured against the final, tuned custom parsing code.)

This code is used to parse whole numbers, real numbers, fractions, and mixed numbers from a string creating an integer from which the (possibly) fractional value can be recovered. example::lcm<T>::as() returns 160,000 as type T for that purpose because 160,000 is the least common multiple of all supported denominators. That aspect of this code should probably be removed in order to concentrate on the parsing, but was too well entrenched for me to remove.

I have changed some names and namespaces from those in the original code to normalize it. I also have omitted exception throwing code and denominator validation logic. I haven't compiled since making those changes, so there may be some minor mistake in the attached code.

The code references some things you'll not have access to, so allow me to explain them so you can make the necessary substitutions.

- core::to_number(), uses TMP to select among several overloads of a conversion function which are wrappers around strtol(), strtod(), etc. Note that specifying a conversion radix is important to avoid octal parsing in the custom code. (Otherwise, the custom code would need to account for leading zeroes in other ways.)

- core::numeric_cast is a function template that converts a string to a numeric type. It uses TMP to select among several overloads of a conversion function which are wrappers around core::to_number() and which log a debug-level message and throw std::bad_cast on failure. boost::lexical_cast should be a slower equivalent.

- ThreadLocal, as you can well infer, manages memory referenced by thread local storage. (It mimics the interface of Rogue Wave's RWTThreadLocal.)

FYI, direct_impl/direct_ exists because I couldn't distinguish its function call operator from one in to_price_impl/price_, without resorting to passing a dummy parameter. While it isn't strictly necessary, I chose to provide it because it avoids using double as an intermediate type.

Notice that the rounding code assumes a positive value and that I manage the sign separately.

The custom version was tuned via profiling, which explains the different treatment of the sign between parsing reals and fractions.

Enjoy!

price.cpp

OvermindDL1

unread,
Jul 13, 2009, 11:38:48 PM7/13/09
to bo...@lists.boost.org


I find this quite interesting. I wonder if I might have the time
tonight to make a Spirit2.1 version of this, the code would certainly
be a great deal shorter.
Just to make sure, from what I gathered looking at the code, you are
trying to parse out a number from an ascii string that could
potentially be an integer (64-bit, just digits, always base 10), a
double (digits as the integer, then a period, then more digits parsed
as the integer, OR a whole integer, then a space(s), followed by an
int then a / then an int), it looks like that a real number can have a
'g' after it, but what is a g? I know what e's means, but g? I am
also confused, it seems your types support int64 as well as double,
but you only ever return an int64, why not a variant of both? Should
I do this for Spirit2.1? Spirit2.1 naturally wants to use such things
anyway so it is actually easier for me to do so, and the user would
have a more accurate value too as they would get either an int64 or a
double depending on what it parsed, I could also add in other
representations like a struct of two int64's for a
numerator/denominator as well for best accuracy. What would you
prefer?

Michael Caisse

unread,
Jul 14, 2009, 12:22:39 AM7/14/09
to bo...@lists.boost.org
OvermindDL1 wrote:
> I find this quite interesting. I wonder if I might have the time
> tonight to make a Spirit2.1 version of this, the code would certainly
> be a great deal shorter.
> Just to make sure, from what I gathered looking at the code, you are
> trying to parse out a number from an ascii string that could
> potentially be an integer (64-bit, just digits, always base 10), a
> double (digits as the integer, then a period, then more digits parsed
> as the integer, OR a whole integer, then a space(s), followed by an
> int then a / then an int), it looks like that a real number can have a
> 'g' after it, but what is a g? I know what e's means, but g? I am
> also confused, it seems your types support int64 as well as double,
> but you only ever return an int64, why not a variant of both? Should
> I do this for Spirit2.1? Spirit2.1 naturally wants to use such things
> anyway so it is actually easier for me to do so, and the user would
> have a more accurate value too as they would get either an int64 or a
> double depending on what it parsed, I could also add in other
> representations like a struct of two int64's for a
> numerator/denominator as well for best accuracy. What would you
> prefer?
> _______________________________________________
>

I have considered doing this myself on and off. I'm still learning
Spirit 2.1 and if you were to throw this together it would be a great
example of approaching the problem three different ways.

I am looking forward to seeing your effort.

Best Regards -
michael


--

----------------------------------
Michael Caisse
Object Modeling Designs
www.objectmodelingdesigns.com

OvermindDL1

unread,
Jul 14, 2009, 12:30:21 AM7/14/09
to bo...@lists.boost.org

Spirit2.1 is by far the most easy Spirit to date, as well as the
fastest, beats out many hand-written and tuned parsers as well.
Should not be hard to do, and I think I would prefer to return a
variant of all possible types as I see no point cutting out
information, let the user decide what info they want, unless someone
tells me they only want anything/everything as an int64, then I can do
it that way too.

But still, what would the 'g' in a number like 2.4g5 do, I know what e
does, but g?

Stewart, Robert

unread,
Jul 14, 2009, 8:15:35 AM7/14/09
to bo...@lists.boost.org
OvermindDL1 wrote:
> On Fri, Jul 10, 2009 at 7:32 AM, Stewart,
> Robert<Robert....@sig.com> wrote:
> > Eric Niebler wrote:
> >> Paul Baxter wrote:
> >> >> Thorsten Ottosen wrote:
> >> >>>
> >> >>> It would be good if you could submit your code as a case in
> >> >>> optimizing expressive code.
[snip]

> >> > This has been an incredibly useful thread. Thanks to you all.
> >> >
> >> > As a potential user put off in the past by concerns over
> >> > abstraction penalties with such libraries (even compile time
> >> > libraries often fail to deliver in all but simple cases), I
> >> > urge Eric to embrace such an example to illustrate just how
> >> > powerful and maintainable a solution based on expressive can
> >> > be.
> >>
> >> I think this is a fine idea. All these tips and tricks are
> >> already described in a doc, but they are not described in depth
> >> from an end-user perspective. I think a performance tuning case
> >> study would make a valuable appendix.
> >>
> >> Robert, can you send me the latest version of your regex
> >> grammar and your hand-coded parser? I'll see what I can do.
> >
> > Sure. I've attached both in one file, but with separate
> > namespaces.
[snip]

> > This code is used to parse whole numbers, real numbers,
> fractions, and mixed numbers from a string creating an
> integer from which the (possibly) fractional value can be
> recovered. example::lcm<T>::as() returns 160,000 as type T
> for that purpose because 160,000 is the least common multiple
> of all supported denominators. That aspect of this code
> should probably be removed in order to concentrate on the
> parsing, but was too well entrenched for me to remove.
[snip]

> I find this quite interesting. I wonder if I might have the
> time tonight to make a Spirit2.1 version of this, the code
> would certainly be a great deal shorter.

That would be great. I am interested to know if I was doing anything wrong or was just trying more than Spirit v2 was capable of doing in Boost 1.37, which is what I needed to use in this case.

> Just to make sure, from what I gathered looking at the code,
> you are trying to parse out a number from an ascii string that
> could potentially be an integer (64-bit, just digits, always
> base 10), a double (digits as the integer, then a period, then
> more digits parsed as the integer, OR a whole integer, then a
> space(s), followed by an int then a / then an int), it looks
> like that a real number can have a 'g' after it, but what is a
> g? I know what e's means, but g?

As described above, I'm looking for whole numbers, reals, fractions, and mixed numbers. The whole numbers are 64b integers. The reals are any of various formats such as you might get from printf(). The "g" and "G" were from a rapid, overzealous scan of the manpage; I forgot to remove them when I realized they weren't appropriate (they are not supported in the custom version, you'll note). The fractions are expected to have a positive denominator, and a possibly signed numerator. The mixed numbers are a whitespace delimited combination of a whole number and a fraction, except the numerator must be non-negative in that case. As you surmised, the input is assumed to be an ASCII string.

> I am also confused, it seems your types support int64 as well
> as double, but you only ever return an int64, why not a variant
> of both?

The purpose of this code was to produce a 64b integer because the result represents a (possibly fractional) dollar amount: a price. The 160,000 least common multiple provides rounding for all supported denominators so all supported amounts can be represented exactly in the 64b integer type (the range is, of course, reduced in doing so).

> Should I do this for Spirit2.1? Spirit2.1 naturally wants to
> use such things anyway so it is actually easier for me to do
> so, and the user would have a more accurate value too as they
> would get either an int64 or a double depending on what it
> parsed, I could also add in other representations like a struct
> of two int64's for a numerator/denominator as well for best
> accuracy. What would you prefer?

In order to compare your Spirit code against the two versions I supplied, your code would need to behave the same. Otherwise, you must alter the two versions I supplied to match what you choose to provide in your Spirit version. The purpose of this exercise is to compare the code and performance, so they must all perform the same task.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Paul Baxter

unread,
Jul 14, 2009, 5:53:29 PM7/14/09
to bo...@lists.boost.org
>
But still, what would the 'g' in a number like 2.4g5 do, I know what e
does, but g?
<
Perhaps this follows the notation for a double much like used in printf
formatting?

http://en.wikipedia.org/wiki/Printf 3/4 of the way down giving an
imprecise but general description

Looking forward to seeing the threeway comparison - really helpful for users
particularly as each trade maintainability, learning curve and speed in
different ways.

OvermindDL1

unread,
Jul 15, 2009, 8:51:53 AM7/15/09
to bo...@lists.boost.org
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;

Stewart, Robert

unread,
Jul 15, 2009, 8:54:00 AM7/15/09
to bo...@lists.boost.org
Paul Baxter wrote:
> >
> But still, what would the 'g' in a number like 2.4g5 do, I know what e
> does, but g?
> <
> Perhaps this follows the notation for a double much like used
> in printf
> formatting?
>
> http://en.wikipedia.org/wiki/Printf 3/4 of the way down giving an
> imprecise but general description

Are you referring to the "Type" table that lists "g" and "G" format specifiers? That's what I latched onto much too readily when scanning the manpage and later realized when working on the custom parsing code but didn't correct in the Xpressive parser. Those are not used in the output; they are used to indicate the desired formatting.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

OvermindDL1

unread,
Jul 15, 2009, 8:57:03 AM7/15/09
to bo...@lists.boost.org
On Wed, Jul 15, 2009 at 6:54 AM, Stewart, Robert<Robert....@sig.com> wrote:
> Paul Baxter wrote:
>> >
>> But still, what would the 'g' in a number like 2.4g5 do, I know what e
>> does, but g?
>> <
>> Perhaps this follows the notation for a double much like used
>> in printf
>> formatting?
>>
>> http://en.wikipedia.org/wiki/Printf   3/4 of the way down giving an
>> imprecise but general description
>
> Are you referring to the "Type" table that lists "g" and "G" format specifiers?  That's what I latched onto much too readily when scanning the manpage and later realized when working on the custom parsing code but didn't correct in the Xpressive parser.  Those are not used in the output; they are used to indicate the desired formatting.

I gathered that, hence my code only supports e/E, no g/G. Look on my
previous email.

OvermindDL1

unread,
Jul 17, 2009, 6:30:32 PM7/17/09
to bo...@lists.boost.org
On Wed, Jul 15, 2009 at 6:57 AM, OvermindDL1<overm...@gmail.com> wrote:
> /* snip */

So has anyone tried the code I posted to see how it compared?

rai...@macrohmasheen.com

unread,
Jul 17, 2009, 7:10:44 PM7/17/09
to bo...@lists.boost.org
I would be very interested in seeing this too as your numbers look extremely good


Sent from my Verizon Wireless BlackBerry

OvermindDL1

unread,
Jul 17, 2009, 7:16:39 PM7/17/09
to bo...@lists.boost.org
On Fri, Jul 17, 2009 at 5:10 PM, <rai...@macrohmasheen.com> wrote:
> I would be very interested in seeing this too as your numbers look extremely good

As stated, the numbers are basically hogwash until all three forms are
all tested on the same hardware using the same compiler. I *might*
have time tonight to work on the code that the others posted above to
get it compilable, although it is rather irritating that they posted
code that was incomplete, but meh. If I have time tonight then I can
test all three versions using MSVC8 on WinXP on my old 1.8ghz Opteron
CPU.

Who knows, one of the other version may still be faster, MSVC does
tend to handle optimizing heavy templated code better then other
compilers, and Spirit is nothing but basically to be inlined templated
code, so it might be able to optimize the xpressive version better as
well, and who knows how it will handle the original code.

Eric Niebler

unread,
Jul 17, 2009, 7:51:06 PM7/17/09
to bo...@lists.boost.org
OvermindDL1 wrote:
> On Fri, Jul 17, 2009 at 5:10 PM, <rai...@macrohmasheen.com> wrote:
>> I would be very interested in seeing this too as your numbers look extremely good
>
> As stated, the numbers are basically hogwash until all three forms are
> all tested on the same hardware using the same compiler. I *might*
> have time tonight to work on the code that the others posted above to
> get it compilable, although it is rather irritating that they posted
> code that was incomplete, but meh. If I have time tonight then I can
> test all three versions using MSVC8 on WinXP on my old 1.8ghz Opteron
> CPU.
>
> Who knows, one of the other version may still be faster, MSVC does
> tend to handle optimizing heavy templated code better then other
> compilers, and Spirit is nothing but basically to be inlined templated
> code, so it might be able to optimize the xpressive version better as
> well, and who knows how it will handle the original code.

I thought Rob posted his code as an attachment here:

http://lists.boost.org/Archives/boost/2009/07/153845.php

Is that not complete?

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com

OvermindDL1

unread,
Jul 17, 2009, 8:35:24 PM7/17/09
to bo...@lists.boost.org
On Fri, Jul 17, 2009 at 5:51 PM, Eric Niebler<er...@boostpro.com> wrote:
> OvermindDL1 wrote:
>>
>> On Fri, Jul 17, 2009 at 5:10 PM, <rai...@macrohmasheen.com> wrote:
>>>
>>> I would be very interested in seeing this too as your numbers look
>>> extremely good
>>
>> As stated, the numbers are basically hogwash until all three forms are
>> all tested on the same hardware using the same compiler.  I *might*
>> have time tonight to work on the code that the others posted above to
>> get it compilable, although it is rather irritating that they posted
>> code that was incomplete, but meh.  If I have time tonight then I can
>> test all three versions using MSVC8 on WinXP on my old 1.8ghz Opteron
>> CPU.
>>
>> Who knows, one of the other version may still be faster, MSVC does
>> tend to handle optimizing heavy templated code better then other
>> compilers, and Spirit is nothing but basically to be inlined templated
>> code, so it might be able to optimize the xpressive version better as
>> well, and who knows how it will handle the original code.
>
> I thought Rob posted his code as an attachment here:
>
> http://lists.boost.org/Archives/boost/2009/07/153845.php
>
> Is that not complete?

Have you tried compiling it? No, it is not complete, first of all it
is missing the includes, as well as a main function to run the loops
and test the timings in. :)

OvermindDL1

unread,
Jul 17, 2009, 10:07:01 PM7/17/09
to bo...@lists.boost.org
On Fri, Jul 17, 2009 at 6:35 PM, OvermindDL1<overm...@gmail.com> wrote:
> /* snip */

Okay, I cannot for the life of me get that above attached price.cpp
file to compile.
It is missing includes (apparently expressive needs something that I
cannot find either). It is missing a whole core:: namespace worth of
functions that both the custom and the xpressive code reference.
Other things too. This code is completely worthless until someone
gives me something complete that I can actually compile.

OvermindDL1

unread,
Jul 18, 2009, 1:32:16 AM7/18/09
to bo...@lists.boost.org
On Fri, Jul 17, 2009 at 8:07 PM, OvermindDL1<overm...@gmail.com> wrote:
> On Fri, Jul 17, 2009 at 6:35 PM, OvermindDL1<overm...@gmail.com> wrote:
>> /* snip */
>
> Okay, I cannot for the life of me get that above attached price.cpp
> file to compile.
> It is missing includes (apparently expressive needs something that I
> cannot find either).  It is missing a whole core:: namespace worth of
> functions that both the custom and the xpressive code reference.
> Other things too.  This code is completely worthless until someone
> gives me something complete that I can actually compile.
>

Okay, I finally got the xpressive version running, and I made a
threadsafe version of the spirit version and a grammar version of the
spirit version. All I need now is some code of the original version
to get that working. I also put in a high-resolution timer and a
testing setup. Here is one run:
Loop count: 10000000
Parsing: 42.5
xpressive: 48.3714
spirit-quick(static): 2.73373
spirit-quick_new(threadsafe): 2.8916
spirit-grammar(threadsafe/reusable): 11.5694
Yes, 7 zero's, not 6, so this test is 10 times slower then what the
other email linked.
xpressive is about 50% faster then the times that other email gave, so
my compiler and processor probably optimize better and run faster.
The Spirit version, even the slowest method, blows it out of the water
though, to put it mildly.

So, if anyone can give me an actual USEFUL version of the above
price.cpp that someone else attached, then I can test the original
customized version.

OvermindDL1

unread,
Jul 18, 2009, 2:37:42 AM7/18/09
to bo...@lists.boost.org
On Fri, Jul 17, 2009 at 11:32 PM, OvermindDL1<overm...@gmail.com> wrote:
> On Fri, Jul 17, 2009 at 8:07 PM, OvermindDL1<overm...@gmail.com> wrote:
>> On Fri, Jul 17, 2009 at 6:35 PM, OvermindDL1<overm...@gmail.com> wrote:
>>> /* snip */
>>
>> Okay, I cannot for the life of me get that above attached price.cpp
>> file to compile.
>> It is missing includes (apparently expressive needs something that I
>> cannot find either).  It is missing a whole core:: namespace worth of
>> functions that both the custom and the xpressive code reference.
>> Other things too.  This code is completely worthless until someone
>> gives me something complete that I can actually compile.
>>
>
> Okay, I finally got the xpressive version running, and I made a
> threadsafe version of the spirit version and a grammar version of the
> spirit version.  All I need now is some code of the original version
> to get that working.  I also put in a high-resolution timer and a
> testing setup.  Here is one run:
> Loop count:  10000000
> Parsing:  42.5
> xpressive:  48.3714
> spirit-quick(static):  2.73373
> spirit-quick_new(threadsafe):  2.8916
> spirit-grammar(threadsafe/reusable):  11.5694

Er, correction, the grammar version I forgot to cache something,
making it much slower then it should have been.
Here are two other correct runs:

Loop count: 1000000
Parsing: 42.5
xpressive: 4.62519
spirit-quick(static): 0.27437
spirit-quick_new(threadsafe): 0.278761
spirit-grammar(threadsafe/reusable): 0.311138

Loop count: 10000000
Parsing: 42.5

xpressive: 46.1108
spirit-quick(static): 2.72641
spirit-quick_new(threadsafe): 2.84515
spirit-grammar(threadsafe/reusable): 3.1393

So yea, this looks a *lot* better.

Michael Caisse

unread,
Jul 18, 2009, 3:46:17 AM7/18/09
to bo...@lists.boost.org
OvermindDL1 wrote:
> Er, correction, the grammar version I forgot to cache something,
> making it much slower then it should have been.
> Here are two other correct runs:
>
> Loop count: 1000000
> Parsing: 42.5
> xpressive: 4.62519
> spirit-quick(static): 0.27437
> spirit-quick_new(threadsafe): 0.278761
> spirit-grammar(threadsafe/reusable): 0.311138
>
> Loop count: 10000000
> Parsing: 42.5
> xpressive: 46.1108
> spirit-quick(static): 2.72641
> spirit-quick_new(threadsafe): 2.84515
> spirit-grammar(threadsafe/reusable): 3.1393
>
> So yea, this looks a *lot* better.
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>

Thank you for pulling this together. Would you mind sharing your test suite?


--

----------------------------------
Michael Caisse
Object Modeling Designs
www.objectmodelingdesigns.com

Eric Niebler

unread,
Jul 18, 2009, 4:13:02 AM7/18/09
to bo...@lists.boost.org
Michael Caisse wrote:
> OvermindDL1 wrote:
>> Parsing: 42.5
<snip>
>> spirit-grammar(threadsafe/reusable): 3.1393

>
> Thank you for pulling this together. Would you mind sharing your test
> suite?

Yes, please. I know Spirit2 is great tech, but I have to wonder how it's
over 10X faster than the hand-coded parser.

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com

OvermindDL1

unread,
Jul 18, 2009, 7:00:44 AM7/18/09
to bo...@lists.boost.org
On Sat, Jul 18, 2009 at 2:13 AM, Eric Niebler<er...@boostpro.com> wrote:
> Michael Caisse wrote:
>>
>> OvermindDL1 wrote:
>>>
>>> Parsing:  42.5
>
> <snip>
>>>
>>> spirit-grammar(threadsafe/reusable):  3.1393
>>
>> Thank you for pulling this together. Would you mind sharing your test
>> suite?

Er, I meant to attach it, it is attached now. :)
It requires Boost trunk, and the timer file hpp I include is part of
the Boost.Spirit2.1 examples/test/somewhere_in_there area, but I
included it with my cpp file too so you do not need to hunt for it.
The defines at the top control what parts to compile or not, 0 to
disable compiling for that part, 1 to enable it.

My build is built with Visual Studio 8 (2005) with SP1. Compiler
options are basically defaults, except getting rid of the secure crt
crap that Microsoft screwed up (enabling that crap slows down Spirit
parsers on my system, a *lot*). The exe I built is in the 7zip file
attached. As stated, I have heard that Visual Studio handles template
stuff like Spirit better then GCC, so I am very curious how GCC's
timings on this file would be. There are still more changes to make
that I intend to make, but I really want the original code in a way
that I can use it.
To be honest, I had to change the core::to_number lines (commented
out) to boost::lexical_cast (right below the commented version), so
the xpressive version could be slightly faster if I actually had the
implementation of core::to_number available, and core::to_number was
well made. The xpressive code also throws a nice 100 line long
warning in my build log, all just about a conversion warning from
double to int_64, no clue how to fix that, I do not know xpressive, so
I would gladly like it if someone could get rid of that nasty warning
in my nice clean buildlog. In my compiler, my Spirit2.1 grammar
builds perfectly clean, I would like it if xpressive was the same way.

I honestly do not know *why* the Spirit version is so much faster then
the xpressive version, the spirit-quick version (the non-threadsafe) I
whipped up in about 2 minutes. The threadsafe version took about 5
minutes, the grammar/threadsafe/reusable version took about 10
minutes, and I know a lot more work was put into the xpressive
version, especially with the auto macros added and all such as well.
I would love it if someone could find out way. If someone else with
MSVC, and someone with GCC and perhaps other things could build it and
display the results that it prints out too, I would be much
appreciative. I do have a linux computer here, but, to be honest, no
clue what to pass to gcc to build something, the command line switches
I pass to MSVC's version is rather monstrous, so trying to convert
that to GCC's seems nightmarish from my point of view.


On Sat, Jul 18, 2009 at 2:13 AM, Eric Niebler<er...@boostpro.com> wrote:
> Yes, please. I know Spirit2 is great tech, but I have to wonder how it's
> over 10X faster than the hand-coded parser.

And I have not tested the hand-coded parser as I cannot get it to
compile. If you can get me a code-complete standalone version of it,
I would be very happy. :)

Either way, Windows users, could you please run the attached exe (that
is in the 7zip file) and paste the results it tells you in an email to
this thread, along with your windows version and basic hardware?

Before I attach this, I am going to run the release exe through a
profiler right quick.

With 1000000 iterations (one million so the xpressive version does not
take so long), with just the xpressive version enabled, the top 10
slowest functions:
CS:EIP Symbol + Offset


64-bit CPU
clocks IPC DC miss rate DTLB L1M L2M rate Misalign rate
Mispredict rate
0x421860 strcmp


2248
1.98 0 0 0 0
0x42bc84 __strgtold12_l


1196
1.1 0 0 0.02 0.01
0x4068a0 std::operator<<<std::char_traits<char> >


744
1.06 0 0 0 0.02
0x41d864 TrailUpVec


686
0.03 0.11 0 0 0
0x40e0e0 std::num_get<char,std::istreambuf_iterator<char,std::char_traits<char>
> >::_Getffld

571
0.94 0 0 0 0.01
0x42d344 __mtold12


447
2.2 0 0 0 0
0x4170a0 std::basic_istream<char,std::char_traits<char> >::operator>>


406
0.38 0 0 0.05 0.08
0x414150 boost::xpressive::detail::posix_charset_matcher<boost::xpressive::cpp_regex_traits<char>
>::match<std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>
>,boost::xpressive::detail::static_xpression<boost::xpressive::detail::true_matcher,
358 1.36 0 0 0
0
0x419231 std::_Lockit::~_Lockit


334
0.26 0 0 0 0
0x42b200 _ld12tod


333
1.05 0 0 0.01 0.01

10 functions, 700 instructions, Total: 48191 samples, 50.01% of
samples in the module, 31.99% of total session samples

So it looks like strcmp i massively hobbling it, taking almost twice
the time of the next highest user. Now for 1000000 (one million) of
just the spirit quick version (all calls, surprisingly few):
CS:EIP Symbol + Offset


64-bit CPU
clocks IPC DC miss rate DTLB L1M L2M rate Misalign rate
Mispredict rate
0x4188c9 _pow_pentium4


358
1.04 0 0 0 0
0x404d70 ??$phrase_parse@PBDU?$expr@Ubitwise_or@tag@proto@boost@@U?$list2@ABU?$expr@Ushift_right@tag@proto@boost@@U?$list2@ABU?$expr@Ushift_right@tag@proto@boost@@U?$list2@ABU?$expr@Usubscript@tag@proto@boost@@U?$list2@ABU?$terminal073d7121f2c9203b84cbac5f1ea1214c
116 1.71 0 0 0
0
0x405080 boost::spirit::qi::detail::real_impl<double,boost::spirit::qi::real_policies<double>
>::parse<char const *,double>

76 1.21 0
0 0 0
0x405f90 boost::spirit::qi::detail::extract_int<__int64,10,1,-1,boost::spirit::qi::detail::positive_accumulator<10>,0>::parse_main<char
const *,__int64>

68 2.35 0 0 0 0
0x405550 boost::spirit::qi::detail::extract_int<double,10,1,-1,boost::spirit::qi::detail::positive_accumulator<10>,0>::parse_main<char
const *,double>

66 1.82 0 0 0 0
0x4053e0 boost::spirit::qi::detail::`anonymous
namespace'::scale_number<double>


63 1.14 0 0 0
0
0x404300 parse_price_spirit_quick<char const *>


62
1.31 0 0 0 0.03
0x4054e0 boost::spirit::qi::detail::fail_function<char const
*,boost::fusion::unused_type const
,boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank,boost::spirit::char_encoding::ascii>
> >::operator()<boost::spirit::qi::action<boost: 59
1.78 0 0 0 0
0x404f30 boost::spirit::qi::skip_over<char const
*,boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank,boost::spirit::char_encoding::ascii>
> >
58 1.59 0 0
0 0
0x417b90 floor


48
0.67 0 0 0 0
0x417b16 _ftol2


46
2.37 0 0 0 0
0x4018f0 dotNumber


42
0.86 0 0 0 0
0x404fa0 boost::spirit::qi::action<boost::spirit::qi::real_parser_impl<double,boost::spirit::qi::real_policies<double>
>,void (__cdecl*)(double)>::parse<char const
*,boost::fusion::unused_type const
,boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::s
41 1.12 0 0 0
0
0x405660 boost::spirit::qi::detail::extract_int<double,10,1,-1,boost::spirit::qi::detail::positive_accumulator<10>,1>::parse_main<char
const *,double>

31 1.29 0 0 0 0
0x417890 _CIpow


31
1.68 0 0 0 0
0x405af0 boost::spirit::qi::int_parser_impl<__int64,10,1,-1>::parse<char
const *,boost::fusion::unused_type const
,boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank,boost::spirit::char_encoding::ascii>
>,__int64> 29 0.48 0
0 0 0
0x405010 boost::spirit::qi::action<boost::spirit::qi::real_parser_impl<double,boost::spirit::qi::real_policies<double>
>,void (__cdecl*)(double)>::parse<char const
*,boost::fusion::unused_type const
,boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::s
27 1.04 0 0 0
0
0x4174c0 _allmul


27
1 0 0 0 0
0x405b60 boost::spirit::qi::not_predicate<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard,1,0>
>::parse<char const *,boost::fusion::unused_type const
,boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank,boost::s
25 1 0 0 0
0
0x404ec0 bo$phrase_parse@PBDU?$expr@Ubitwise_or@tag@proto@boost@@U?$list2@ABU?$expr@Ushift_right@tag@proto@boost@@U?$list2@ABU?$expr@Ushift_right@tag@proto@boost@@U?$list2@ABU?$expr@Usubscript@tag@proto@boost@@U?$list2@ABU?$terminal073d7121f2c9203b84cbac5f1ea1214c
23 0.17 0 0 0
0.12
0x417bd0 _floor_pentium4


17
0.24 0 0 0 0
0x4188b0 _CIpow_pentium4


14
0 0 0 0 0
0x401970 main


9
0.11 0 0 0 0.3
0x404f10 boost::spirit::qi::skip_over<char const
*,boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank,boost::spirit::char_encoding::ascii>
> >
4 0 0 0
0 0
0x40cc02 _flsbuf


1
0 0 0 0 0
0x40e8b0 __SEH_prolog4


0
0 0 0 0 0

26 functions, 447 instructions, Total: 6513 samples, 100.00% of
samples in the module, 69.20% of total session samples


Now for the same, but with the spirit grammar version, since it is so
much slower then the quick for some reason (all calls again, not that
many):
CS:EIP Symbol + Offset


64-bit CPU
clocks IPC DC miss rate DTLB L1M L2M rate Misalign rate
Mispredict rate
0x419909 _pow_pentium4


365
0.97 0 0 0 0
0x4056a0 boost::function4<bool,char const * &,char const * const
&,boost::spirit::context<boost::fusion::cons<__int64
&,boost::fusion::nil>,boost::fusion::vector0<void> >
&,boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank,boost::sp
129 1.19 0 0 0
0.02
0x405780 boost::detail::function::function_obj_invoker4<boost::spirit::qi::detail::parser_binder<boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<char
const *,__int64 __cdecl(void),boost::proto::exprns_::expr<boos
99 1.12 0 0 0
0.03
0x406f50 boost::spirit::qi::detail::extract_int<__int64,10,1,-1,boost::spirit::qi::detail::positive_accumulator<10>,0>::parse_main<char
const *,__int64>

81 1.28 0 0 0 0
0x406100 boost::spirit::qi::detail::real_impl<double,boost::spirit::qi::real_policies<double>
>::parse<char const *,double>

77 1.38 0
0 0 0
0x406bc0 boost::spirit::qi::rule<char const *,__int64
__cdecl(void),boost::proto::exprns_::expr<boost::proto::tag::terminal,boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank,boost::spirit::char_encoding::ascii>
>,0>,boost::fusion::unu 77 0.87 0 0
0 0.04
0x406c30 boost::spirit::qi::action<boost::spirit::qi::int_parser_impl<__int64,10,1,-1>,boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,boost::fusion::vector<boost::spirit::attribute<0>,boost::phoenix::composite<boost::phoenix::multiplies_ev
74 1.61 0 0 0
0
0x406620 boost::spirit::qi::detail::extract_int<double,10,1,-1,boost::spirit::qi::detail::positive_accumulator<10>,0>::parse_main<char
const *,double>

64 1.22 0 0 0 0
0x4050b0 boost::spirit::qi::phrase_parse<char const
*,price_grammar<char const
*>,boost::proto::exprns_::expr<boost::proto::tag::terminal,boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank,boost::spirit::char_encoding::ascii>
>,0>,__in 56 0.29 0 0
0 0.11
0x406460 boost::spirit::qi::detail::`anonymous
namespace'::scale_number<double>


53 1.79 0 0 0
0
0x405810 boost::detail::function::function_obj_invoker4<boost::spirit::qi::detail::parser_binder<boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<char
const *,__int64 __cdecl(void),boost::proto::exprns_::expr<boos
52 1.98 0 0 0
0.02
0x418b56 _ftol2


50
1.68 0 0 0 0
0x401940 main


45
0.67 0 0 0 0.04
0x405fe0 boost::spirit::traits::action_dispatch<boost::spirit::qi::real_parser_impl<double,boost::spirit::qi::real_policies<double>
> >::operator()<dot_number_to_long_long_function,double,boost::spirit::context<boost::fusion::cons<__int64
&,boost::fusion::nil>,boost:: 43 1.19 0
0 0 0
0x405f70 boost::spirit::qi::action<boost::spirit::qi::real_parser_impl<double,boost::spirit::qi::real_policies<double>
>,dot_number_to_long_long_function>::parse<char const
*,boost::spirit::context<boost::fusion::cons<__int64
&,boost::fusion::nil>,boost::fusion::vecto 41 0.83
0 0 0 0
0x405930 boost::detail::function::function_obj_invoker4<boost::spirit::qi::detail::parser_binder<boost::spirit::qi::action<boost::spirit::qi::real_parser_impl<double,boost::spirit::qi::real_policies<double>
>,dot_number_to_long_long_function>,boost::mpl::bool_<0> >,bo
36 2 0 0 0 0
0x418bd0 floor


34
1.12 0 0 0 0
0x405e60 boost::spirit::qi::action<boost::spirit::qi::real_parser_impl<double,boost::spirit::qi::real_policies<double>
>,dot_number_to_long_long_function>::parse<char const
*,boost::spirit::context<boost::fusion::cons<__int64
&,boost::fusion::nil>,boost::fusion::vecto 33 0.15
0 0 0 0.28
0x4182a0 _allmul


33
3.42 0 0 0 0
0x4188d0 _CIpow


27
0.52 0 0 0 0
0x406730 boost::spirit::qi::detail::extract_int<double,10,1,-1,boost::spirit::qi::detail::positive_accumulator<10>,1>::parse_main<char
const *,double>

26 2.62 0 0 0 0
0x406560 boost::spirit::qi::int_parser_impl<__int64,10,1,-1>::parse<char
const *,boost::spirit::context<boost::fusion::cons<__int64
&,boost::fusion::nil>,boost::fusion::vector0<void>
>,boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::bla
19 0.16 0 0 0
0
0x418c10 _floor_pentium4


16
0 0 0 0 0
0x406ca0 boost::spirit::qi::not_predicate<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard,1,0>
>::parse<char const
*,boost::spirit::context<boost::fusion::cons<__int64
&,boost::fusion::nil>,boost::fusion::vector0<void>
>,boost::spirit::qi::char_ 11 0.36 0 0
0 0
0x4198f0 _CIpow_pentium4


11
0 0 0 0 0
0x40b090 _flush


1
0 0 0 0 0

26 functions, 451 instructions, Total: 7342 samples, 100.00% of
samples in the module, 71.73% of total session samples

Spirit_Price_exe.7z
Spirit_Price_Code.7z

Eric Niebler

unread,
Jul 18, 2009, 11:15:02 AM7/18/09
to bo...@lists.boost.org
OvermindDL1 wrote:
> To be honest, I had to change the core::to_number lines (commented
> out) to boost::lexical_cast (right below the commented version), so
> the xpressive version could be slightly faster if I actually had the
> implementation of core::to_number available, and core::to_number was
> well made.

This could very well be the source of a major slow-down. Doesn't
lexical_cast use string streams to do the conversion? It seems to me
that you're comparing apples to oranges.

Also, the warning you saw came from the user-created semantic action,
not from xpressive.

Robert, can you please post your complete code so that we can actually
have meaningful numbers to look at? Thanks.

John Bytheway

unread,
Jul 18, 2009, 3:51:19 PM7/18/09
to bo...@lists.boost.org
OvermindDL1 wrote:
<snip>

> As stated, I have heard that Visual Studio handles template
> stuff like Spirit better then GCC, so I am very curious how GCC's
> timings on this file would be.

Alas, gcc doesn't do so well. I had to make a few tweaks to your code
(you typedefed int64_t at global scope which clashes with the one in the
C library headers, and you used an INT64 macro which doesn't exist here)
but then I got a very long error ending with this:

.../boost-trunk/boost/proto/transform/call.hpp:146: internal compiler
error: Segmentation fault

I guess the metaprogramming is too much for it :(.

That was with -O3 -DNDEBUG -march=native and gcc version:
gcc (Gentoo 4.3.3-r2 p1.2, pie-10.1.5) 4.3.3


So then I tried icc 10.1 (essentially same options) which takes over a
minute to compile this, but does succeed. With that I got:

$ ./price-icc


Loop count: 10000000
Parsing: 42.5

xpressive: 27.4704
spirit-quick(static): 1.58132
spirit-quick_new(threadsafe): 1.52971
spirit-grammar(threadsafe/reusable): 1.64666

which are much the same as your results (except ~1.7 times faster all
round), but the Parsing result is obviously meaningless and the
xpressive also dubious because of lexical_cast.

I then tried with icc's inter-procedural optimisations turned on too,
which improves the xpressive code significantly, but doesn't obviously
affect spirit:

$ ./price-icc-ipo


Loop count: 10000000
Parsing: 42.5

xpressive: 17.3577
spirit-quick(static): 1.52487
spirit-quick_new(threadsafe): 1.51834
spirit-grammar(threadsafe/reusable): 1.65164

Finally I used static linking, and the xpressive time improved again,
and maybe the others a little. This surprised me.

$ ./price-icc-ipo-static


Loop count: 10000000
Parsing: 42.5

xpressive: 12.6157
spirit-quick(static): 1.49887
spirit-quick_new(threadsafe): 1.48146
spirit-grammar(threadsafe/reusable): 1.62731

John Bytheway

OvermindDL1

unread,
Jul 18, 2009, 8:44:05 PM7/18/09
to bo...@lists.boost.org
On Sat, Jul 18, 2009 at 9:15 AM, Eric Niebler<er...@boostpro.com> wrote:
> OvermindDL1 wrote:
>>
>> To be honest, I had to change the core::to_number lines (commented
>> out) to boost::lexical_cast (right below the commented version), so
>> the xpressive version could be slightly faster if I actually had the
>> implementation of core::to_number available, and core::to_number was
>> well made.
>
> This could very well be the source of a major slow-down. Doesn't
> lexical_cast use string streams to do the conversion? It seems to me that
> you're comparing apples to oranges.

Yes, as I complained about multiple times in this thread about people
not posting complete code snippets, what am I supposed to make of a
function call that does not exist?


On Sat, Jul 18, 2009 at 1:51 PM, John Bytheway<jbythew...@gmail.com> wrote:
> OvermindDL1 wrote:
> <snip>
>> As stated, I have heard that Visual Studio handles template
>> stuff like Spirit better then GCC, so I am very curious how GCC's
>> timings on this file would be.
>
> Alas, gcc doesn't do so well.  I had to make a few tweaks to your code
> (you typedefed int64_t at global scope which clashes with the one in the
> C library headers, and you used an INT64 macro which doesn't exist here)
> but then I got a very long error ending with this:
>
> .../boost-trunk/boost/proto/transform/call.hpp:146: internal compiler
> error: Segmentation fault
>
> I guess the metaprogramming is too much for it :(.
>
> That was with -O3 -DNDEBUG -march=native and gcc version:
> gcc (Gentoo 4.3.3-r2 p1.2, pie-10.1.5) 4.3.3

I do not get that, GCC usually handles more templates then MSVC ever
has, just usually not as optimized, so I do not understand how you
could be getting a compiler error.

Regardless, all of these numbers and times are vastly higher then what
the previous person posted, so very nice. We just need the compilable
original code to see how it compares now.

Hmm, I might try to replace all the lexical_cast's with a spirit
parser for just that number, for a single extraction like that, Spirit
compiles to *very* little assembly, quite impressive actually.

Hartmut Kaiser

unread,
Jul 18, 2009, 9:50:18 PM7/18/09
to bo...@lists.boost.org

Here are my results (platform: Windows7, Intel Core Duo(tm) Processor,
2.8GHz, 4GByte RAM), I reduced the number of iterations to 1e6.

VC8SP1/32Bit


Loop count: 1000000
Parsing: 42.5

xpressive: 4.53867
spirit-quick(static): 0.213174
spirit-quick_new(threadsafe): 0.255517
spirit-grammar(threadsafe/reusable): 0.228167

VC10 beta/32Bit:


Loop count: 1000000
Parsing: 42.5

xpressive: 4.68044
spirit-quick(static): 0.245641
spirit-quick_new(threadsafe): 0.279981
spirit-grammar(threadsafe/reusable): 0.252697

VC10 beta/64Bit:


Loop count: 1000000
Parsing: 42.5

xpressive: 3.7877
spirit-quick(static): 0.17625
spirit-quick_new(threadsafe): 0.175377
spirit-grammar(threadsafe/reusable): 0.137707

gcc 4.4.1 (MinGW)/32bit


Loop count: 1000000
Parsing: 42.5

xpressive: 13.5003
spirit-quick(static): 0.274027
spirit-quick_new(threadsafe): 0.261029
spirit-grammar(threadsafe/reusable): 0.325813

gcc 4.4.1 (MinGW)/64bit


Loop count: 1000000
Parsing: 42.5

xpressive: 10.2381
spirit-quick(static): 0.0868965
spirit-quick_new(threadsafe): 0.0820163
spirit-grammar(threadsafe/reusable): 0.228892

Regards Hartmut

OvermindDL1

unread,
Jul 18, 2009, 10:09:43 PM7/18/09
to bo...@lists.boost.org

Very nice and detailed, thanks.

I just changed the file to use spirit for parsing where I had used
lexical_cast got very different timings for xpressive now, so now,
with xpressive using a bit of spirit I get:


Loop count: 10000000
Parsing: 42.5

xpressive: 15.4841
spirit-quick(static): 3.01117
spirit-quick_new(threadsafe): 3.10548
spirit-grammar(threadsafe/reusable): 3.81694

Vast increase, 3x faster xpressive is now.
Also, how do you fix that rather bloody massive warning about
double->int64 truncation?
I also changed all int64_t to boost::long_long_type since they are the
same thing anyway (on 32-bit at least?), as well as it being
multi-platform unlike int64_t.
My changed file is attached. Do not know if this is considered
cheating now that xpressive is using some spirit now. ;-)

Spirit_Price_Code1.7z

John Bytheway

unread,
Jul 19, 2009, 4:29:38 AM7/19/09
to bo...@lists.boost.org
OvermindDL1 wrote:
> I just changed the file to use spirit for parsing where I had used
> lexical_cast got very different timings for xpressive now, so now,
> with xpressive using a bit of spirit I get:
> Loop count: 10000000
> Parsing: 42.5
> xpressive: 15.4841
> spirit-quick(static): 3.01117
> spirit-quick_new(threadsafe): 3.10548
> spirit-grammar(threadsafe/reusable): 3.81694
>
> Vast increase, 3x faster xpressive is now.
> Also, how do you fix that rather bloody massive warning about
> double->int64 truncation?
> I also changed all int64_t to boost::long_long_type since they are the
> same thing anyway (on 32-bit at least?), as well as it being
> multi-platform unlike int64_t.
> My changed file is attached. Do not know if this is considered
> cheating now that xpressive is using some spirit now. ;-)


That one doesn't compile for me. On line 402:

boost::spirit::qi::parse(va.begin(), va.end(),
boost::spirit::double_[boost::phoenix::ref(value)]);

I get

no instance of overloaded function "boost::spirit::qi::parse" matches
the argument list

(and the same on all the similar lines)

and indeed I see can't see an appropriate overload in the spirit headers
(in boost trunk), but it's hard to be sure since there are so many
functions called parse!

John Bytheway

OvermindDL1

unread,
Jul 19, 2009, 5:28:39 AM7/19/09
to bo...@lists.boost.org

You are running Boost Trunk? Compiles fine here in MSVC, and I last
synced to trunk less then a week ago.

Joel de Guzman

unread,
Jul 19, 2009, 6:03:51 AM7/19/09
to bo...@lists.boost.org
OvermindDL1 wrote:

> I just changed the file to use spirit for parsing where I had used
> lexical_cast got very different timings for xpressive now, so now,
> with xpressive using a bit of spirit I get:
> Loop count: 10000000
> Parsing: 42.5
> xpressive: 15.4841
> spirit-quick(static): 3.01117
> spirit-quick_new(threadsafe): 3.10548
> spirit-grammar(threadsafe/reusable): 3.81694
>
> Vast increase, 3x faster xpressive is now.
> Also, how do you fix that rather bloody massive warning about
> double->int64 truncation?
> I also changed all int64_t to boost::long_long_type since they are the
> same thing anyway (on 32-bit at least?), as well as it being
> multi-platform unlike int64_t.
> My changed file is attached. Do not know if this is considered
> cheating now that xpressive is using some spirit now. ;-)

This is somewhat cheating. We've tuned the numeric parsers of Spirit
with TMP tricks, loop unrolling, etc. Those are very finely tuned
numeric parsers you see there that beats the fastest C code such as
strtol and atoi. The following benchmarks reveal 2X+ speed against
low level strtol and atoi (attached). I am getting:

atoi: 0.82528 [s]
strtol: 0.792227 [s]
int_: 0.358016 [s]

The first and second are the low-level C routines. The third is
Spirit's int_ parser. I need not mention that the C routines only
accept C strings while the Spirit int_ parser can accept any
forward iterator. So, in a sense, we're comparing apples and
oranges. But this goes to show that you can write highly optimized
code in generic C++.

Regards,
--
Joel de Guzman
http://www.boostpro.com
http://spirit.sf.net

uint_parser.cpp

Joel de Guzman

unread,
Jul 19, 2009, 6:07:25 AM7/19/09
to bo...@lists.boost.org

Oh, BTW, that's MSVC 9, on a Core 2 Duo 2.4 Ghz, 3MB RAM.

_______________________________________________

Edward Grace

unread,
Jul 19, 2009, 7:27:52 AM7/19/09
to bo...@lists.boost.org
> This is somewhat cheating. We've tuned the numeric parsers of Spirit
> with TMP tricks, loop unrolling, etc. Those are very finely tuned
> numeric parsers you see there that beats the fastest C code such as
> strtol and atoi. The following benchmarks reveal 2X+ speed against
> low level strtol and atoi (attached). I am getting:
>
> atoi: 0.82528 [s]
> strtol: 0.792227 [s]
> int_: 0.358016 [s]
>
> The first and second are the low-level C routines. The third is
> Spirit's int_ parser. I need not mention that the C routines only
> accept C strings while the Spirit int_ parser can accept any
> forward iterator. So, in a sense, we're comparing apples and
> oranges. But this goes to show that you can write highly optimized
> code in generic C++.


Dear Joel,

Would you mind trying out these examples with my timer? I'd like to
see if it gives sensible answers for other people's code on other
people's machines. Attached is a reworking of your testbed code
using my timer which can be obtained from boost vault,

http://tinyurl.com/ksbukc

I haven't been able to try compiling the attached modification to
your code myself as I don't have the boost spirit libraries. Even if
I did it still wouldn't be your machine! Since I can't compile it
there *will* be some errors! The ugly global variables are sadly an
unavoidable side effect at the moment.

I have pared down the number of iterations quite significantly. The
generic_timer makes repeated calls to the functions under test - as
many as necessary to 'get the job done' - so there's no need to have
large run-times in order to effectively get an average time.

Cheers,

-ed

ejg_uint_parser.cpp

Joel de Guzman

unread,
Jul 19, 2009, 9:16:28 AM7/19/09
to bo...@lists.boost.org
Edward Grace wrote:
>> This is somewhat cheating. We've tuned the numeric parsers of Spirit
>> with TMP tricks, loop unrolling, etc. Those are very finely tuned
>> numeric parsers you see there that beats the fastest C code such as
>> strtol and atoi. The following benchmarks reveal 2X+ speed against
>> low level strtol and atoi (attached). I am getting:
>>
>> atoi: 0.82528 [s]
>> strtol: 0.792227 [s]
>> int_: 0.358016 [s]
>>
>> The first and second are the low-level C routines. The third is
>> Spirit's int_ parser. I need not mention that the C routines only
>> accept C strings while the Spirit int_ parser can accept any
>> forward iterator. So, in a sense, we're comparing apples and
>> oranges. But this goes to show that you can write highly optimized
>> code in generic C++.
>
>
> Dear Joel,
>
> Would you mind trying out these examples with my timer? I'd like to see
> if it gives sensible answers for other people's code on other people's
> machines. Attached is a reworking of your testbed code using my timer
> which can be obtained from boost vault,

Hi Edward,

I tried a quick shot at it. There are compilation errors indeed.
Please try to fix the errors first (*). You can get Spirit by getting
the Boost trunk off SVN.

(*) Also, please make sure you try it on Windows too. E.g. <sys/time.h>
is non-standard, AFAIK. My main compiler is VC9. Your library is
intended to be cross platform, right?

_______________________________________________

Edward Grace

unread,
Jul 19, 2009, 9:27:03 AM7/19/09
to bo...@lists.boost.org
> There are compilation errors indeed.

If you've tried building example_timer.cpp can you post up the errors
you're getting? I don't have access to a Windows machine.

> Please try to fix the errors first (*). You can get Spirit by getting
> the Boost trunk off SVN.

Ok, will do.

> (*) Also, please make sure you try it on Windows too. E.g. <sys/
> time.h>
> is non-standard, AFAIK.

No can do, I don't have access to a windows machine.

The <sys/time.h> is just for gettimeofday().

The actual generic_timer is chronometer agnostic (or should be) so
any function you have to get a given high precision time should just
'go'. Perhaps if you post up your timer I can try that - or at least
make an interface that will work.

> My main compiler is VC9. Your library is
> intended to be cross platform, right?

Indeed, *intended* is the operative word. I've only tried it on OS X
and Linux.

-ed
------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

Joel de Guzman

unread,
Jul 19, 2009, 9:34:39 AM7/19/09
to bo...@lists.boost.org
Edward Grace wrote:

> The actual generic_timer is chronometer agnostic (or should be) so any
> function you have to get a given high precision time should just 'go'.
> Perhaps if you post up your timer I can try that - or at least make an
> interface that will work.

I believe Overmind posted that sometime ago included in the 7Z file
"Spirit_Price_Code1.7z"

Cheers,

_______________________________________________

John Bytheway

unread,
Jul 19, 2009, 9:46:33 AM7/19/09
to bo...@lists.boost.org
OvermindDL1 wrote:
> On Sun, Jul 19, 2009 at 2:29 AM, John Bytheway<jbythew...@gmail.com> wrote:
>> That one doesn't compile for me. On line 402:
>>
>> boost::spirit::qi::parse(va.begin(), va.end(),
>> boost::spirit::double_[boost::phoenix::ref(value)]);
>>
>> I get
>>
>> no instance of overloaded function "boost::spirit::qi::parse" matches
>> the argument list
>
> You are running Boost Trunk? Compiles fine here in MSVC, and I last
> synced to trunk less then a week ago.

The problem is that parse takes its first argument by reference, and
va.begin() is a temporary. If I take a copy of va.begin() and pass that
it works fine. I don't see how this compiled in MSVC (does
string::begin() return a non-const reference?), but anyway. Here are
the icc results (Intel Core2 Quad 2.83GHz, Gentoo):

Loop count: 10000000
Parsing: 42.5

xpressive: 4.28591
spirit-quick(static): 1.4721
spirit-quick_new(threadsafe): 1.46949
spirit-grammar(threadsafe/reusable): 1.59846

and gcc-4.4.0:

Loop count: 10000000
Parsing: 42.5

xpressive: 3.62948
spirit-quick(static): 1.02657
spirit-quick_new(threadsafe): 1.00637
spirit-grammar(threadsafe/reusable): 1.01748

gcc 4.3 is still ICEing.

John Bytheway

Hartmut Kaiser

unread,
Jul 19, 2009, 10:14:10 AM7/19/09
to bo...@lists.boost.org

Slightly off-topic, but in order to emphasize what Joel said, here are a
couple of benchmark results I published a couple of days ago related to
output formatting: http://tinyurl.com/n4368t. Just an excerpt (Intel Core
Duo(tm) Processor, 2.8GHz, 4GByte RAM, Intel 11.1/64Bit):

Performance comparison for formatting a single double (all times in [s],
1000000 iterations):
sprintf: 0.694
iostreams: 1.354
Boost.Format: 2.011
Karma double_: 0.218

(where double_ is the Spirit.Karma output generator for a default floating
point format)

Joel de Guzman

unread,
Jul 19, 2009, 10:46:21 AM7/19/09
to bo...@lists.boost.org
John Bytheway wrote:

> string::begin() return a non-const reference?), but anyway. Here are
> the icc results (Intel Core2 Quad 2.83GHz, Gentoo):
>
> Loop count: 10000000
> Parsing: 42.5
> xpressive: 4.28591
> spirit-quick(static): 1.4721
> spirit-quick_new(threadsafe): 1.46949
> spirit-grammar(threadsafe/reusable): 1.59846
>
> and gcc-4.4.0:
>
> Loop count: 10000000
> Parsing: 42.5
> xpressive: 3.62948
> spirit-quick(static): 1.02657
> spirit-quick_new(threadsafe): 1.00637
> spirit-grammar(threadsafe/reusable): 1.01748
>
> gcc 4.3 is still ICEing.

Those are good numbers. It shows that the effect of the
virtual function call of the spirit grammar rules is obviated
out of existence!

For the record, this one shows the xpressive code using spirit
numeric parsers to convert the string to numbers, right?
Will the original OP please (PLEASE!) come forward and post his
original hand-coded program? This is SOOO confusing!

Regards,

_______________________________________________

Edward Grace

unread,
Jul 19, 2009, 2:10:44 PM7/19/09
to bo...@lists.boost.org

On 19 Jul 2009, at 14:34, Joel de Guzman wrote:

> Edward Grace wrote:
>
>> The actual generic_timer is chronometer agnostic (or should be) so
>> any
>> function you have to get a given high precision time should just
>> 'go'.
>> Perhaps if you post up your timer I can try that - or at least
>> make an
>> interface that will work.
>
> I believe Overmind posted that sometime ago included in the 7Z file
> "Spirit_Price_Code1.7z"

Hi Joel,

It appears to be in your SVN tree - however it doesn't really help.
It seems to be unapologetically Windows only.

I tried to compile your example but was unsure of what to pull from
the SVN tree. Is it Spirit2? Could you please supply the precise
svn repository? I tried these two:

svn checkout https://spirit.svn.sourceforge.net/svnroot/spirit/
trunk/final/boost/
svn checkout https://spirit.svn.sourceforge.net/svnroot/spirit/
trunk/Spirit2x/

but wasn't sure which (if anything) was correct, so didn't know if
the errors I was getting were because I was looking at the wrong
thing or doing something dim.

Regarding a cross-platform high frequency timer, I have uploaded
"cycle.h" from the FFTW project to the Boost Vault,

http://tinyurl.com/maylnc

This appears to support a wide variety of platforms and compilers in
a transparent manner. You end up with a call to a function of the form.

ticks getticks();

on whatever platform you are using (thanks to some macro magic). It
should work just fine with Windows and MSVC.

The following

#include "cycle.h"
#include <iostream>
int main() {
std::cout << getticks() << std::endl;
return 0;
}

should spit out a large number, usually the number of clock cycles
since the CPU started.

$ g++-4 -ansi -pedantic test.cpp
In file included from test.cpp:3:
cycle.h:172: warning: ISO C++ 1998 does not support 'long long'
$ ./a.out
32572590328070

If you could confirm that the above snippet works for you and the
appropriate SVN repository I'll have a bash at that timing again.

After all, if it's written in a standards compliant platform agnostic
manner if it works for me it's got to work for you ---------- right? ;-)

Cheers,

-ed

Hartmut Kaiser

unread,
Jul 19, 2009, 2:30:31 PM7/19/09
to bo...@lists.boost.org
> >> The actual generic_timer is chronometer agnostic (or should be) so
> >> any
> >> function you have to get a given high precision time should just
> >> 'go'.
> >> Perhaps if you post up your timer I can try that - or at least
> >> make an
> >> interface that will work.
> >
> > I believe Overmind posted that sometime ago included in the 7Z file
> > "Spirit_Price_Code1.7z"
>
> Hi Joel,
>
> It appears to be in your SVN tree - however it doesn't really help.
> It seems to be unapologetically Windows only.

Nope, the high_resolution timer components is cross platform. I tested it on
Windows, Linux, and MacOS.

> I tried to compile your example but was unsure of what to pull from
> the SVN tree. Is it Spirit2? Could you please supply the precise
> svn repository? I tried these two:
>
> svn checkout https://spirit.svn.sourceforge.net/svnroot/spirit/
> trunk/final/boost/
> svn checkout https://spirit.svn.sourceforge.net/svnroot/spirit/
> trunk/Spirit2x/
>
> but wasn't sure which (if anything) was correct, so didn't know if
> the errors I was getting were because I was looking at the wrong
> thing or doing something dim.

Please use Boost SVN trunk here:

https://svn.boost.org/svn/boost/trunk/boost/spirit
https://svn.boost.org/svn/boost/trunk/libs/spirit

and make sure to put these directories in front of your normal Boost
installation (V1.37 is required at minimum). The high_resultion_timer.hpp is
here:

https://svn.boost.org/svn/boost/trunk/libs/spirit/benchmarks/high_resolution
_timer.hpp

HTH
Regards Hartmut

Edward Grace

unread,
Jul 19, 2009, 2:50:45 PM7/19/09
to bo...@lists.boost.org

Dear Hartmut,

>> It appears to be in your SVN tree - however it doesn't really help.
>> It seems to be unapologetically Windows only.
>
> Nope, the high_resolution timer components is cross platform. I
> tested it on
> Windows, Linux, and MacOS.

This is what I found, when I went searching

https://spirit.svn.sourceforge.net/svnroot/spirit/trunk/final/boost/
high_resolution_timer.hpp

clearly I was looking in the wrong place!

Thanks.


-ed

John Bytheway

unread,
Jul 19, 2009, 3:15:35 PM7/19/09
to bo...@lists.boost.org
Joel de Guzman wrote:
> John Bytheway wrote:
>
>> string::begin() return a non-const reference?), but anyway. Here are
>> the icc results (Intel Core2 Quad 2.83GHz, Gentoo):
>>
>> Loop count: 10000000
>> Parsing: 42.5
>> xpressive: 4.28591
>> spirit-quick(static): 1.4721
>> spirit-quick_new(threadsafe): 1.46949
>> spirit-grammar(threadsafe/reusable): 1.59846
>>
>> and gcc-4.4.0:
>>
>> Loop count: 10000000
>> Parsing: 42.5
>> xpressive: 3.62948
>> spirit-quick(static): 1.02657
>> spirit-quick_new(threadsafe): 1.00637
>> spirit-grammar(threadsafe/reusable): 1.01748
>>
>> gcc 4.3 is still ICEing.
>
> Those are good numbers. It shows that the effect of the
> virtual function call of the spirit grammar rules is obviated
> out of existence!
>
> For the record, this one shows the xpressive code using spirit
> numeric parsers to convert the string to numbers, right?

Correct.

> Will the original OP please (PLEASE!) come forward and post his
> original hand-coded program? This is SOOO confusing!

Well, in case he doesn't, I've thrown together an implementation of
core::to_number based on Robert's description of it. I had to guess at
the interface, and I didn't verify correctness. I also had to implement
two error routines; I made them both "throw 0;".

I also tweaked the xpressive code so that it didn't copy the sub_match
objects to strings before using qi to parse out the doubles and ints.
That sped it up slightly (gcc 4.4.0 again):

Loop count: 10000000
Parsing: 42.5

original-custom: 2.08637
xpressive: 2.94329
spirit-quick(static): 1.02784
spirit-quick_new(threadsafe): 1.03306
spirit-grammar(threadsafe/reusable): 1.00213

although I'm slightly concerned with what happened when I changed the
string to be parsed:

Loop count: 10000000
Parsing: 425/500
original-custom: 1.6307
xpressive: 116.992
spirit-quick(static): 0.552722
spirit-quick_new(threadsafe): 0.53429
spirit-grammar(threadsafe/reusable): 0.680257

Why is the xpressive code so slow here? The parsing is more complex in
this case, but I wouldn't think it was this bad! Perhaps I broke it
somehow...

New code attached (also includes other minor changes I had to make to
get things to compile).

If someone writes core::numeric_cast then the 'original' xpressive code
can be used.

John Bytheway

Spirit_Price.cpp

Edward Grace

unread,
Jul 19, 2009, 3:33:12 PM7/19/09
to bo...@lists.boost.org
> Please use Boost SVN trunk here:
>
> https://svn.boost.org/svn/boost/trunk/boost/spirit
> https://svn.boost.org/svn/boost/trunk/libs/spirit
>
> and make sure to put these directories in front of your normal Boost
> installation (V1.37 is required at minimum). The
> high_resultion_timer.hpp is
> here:
>
> https://svn.boost.org/svn/boost/trunk/libs/spirit/benchmarks/
> high_resolution
> _timer.hpp
>

Hi Hartmut,

So,

I did the following and placed them in different directories.
$ svn checkout https://svn.boost.org/svn/boost/trunk/boost/spirit
$ svn checkout https://svn.boost.org/svn/boost/trunk/libs/spirit

In both cases it states "Checked out revision 55030".

And shoved high_resolution_timer.hpp in the appropriate place.

After modifying "uint_parser.cpp" to add

#include <iostream>

I get the following error:

$ g++-4 -I ~/Desktop/boost_spirit/ -I ~Desktop/libs_spirit/ -I ~/
Desktop/boost_1_39_0 -o uint_parser uint_parser.cpp
uint_parser.cpp: In function 'int main()':
uint_parser.cpp:37: error: 'qi::int_' has not been declared
uint_parser.cpp:104: error: 'int_' was not declared in this scope

which seems fairly fundamental.

Do I have the correct revision of Spirit? Any suggestions?

-ed

------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

Hartmut Kaiser

unread,
Jul 19, 2009, 3:44:06 PM7/19/09
to bo...@lists.boost.org
> > Please use Boost SVN trunk here:
> >
> > https://svn.boost.org/svn/boost/trunk/boost/spirit
> > https://svn.boost.org/svn/boost/trunk/libs/spirit
> >
> > and make sure to put these directories in front of your normal Boost
> > installation (V1.37 is required at minimum). The
> > high_resultion_timer.hpp is
> > here:
> >
> > https://svn.boost.org/svn/boost/trunk/libs/spirit/benchmarks/
> > high_resolution
> > _timer.hpp
> >
>
> Hi Hartmut,
>
> So,
>
> I did the following and placed them in different directories.
> $ svn checkout https://svn.boost.org/svn/boost/trunk/boost/spirit
> $ svn checkout https://svn.boost.org/svn/boost/trunk/libs/spirit
>
> In both cases it states "Checked out revision 55030".
>
> And shoved high_resolution_timer.hpp in the appropriate place.
>
> After modifying "uint_parser.cpp" to add
>
> #include <iostream>
>
> I get the following error:
>
> $ g++-4 -I ~/Desktop/boost_spirit/ -I ~Desktop/libs_spirit/ -I ~/
> Desktop/boost_1_39_0 -o uint_parser uint_parser.cpp

You don't need to add the libs/spirit directory to your sinclude path.
That's just where the examples, tests and documentation resides. Sorry, I
should have been more explicit.

> uint_parser.cpp: In function 'int main()':
> uint_parser.cpp:37: error: 'qi::int_' has not been declared
> uint_parser.cpp:104: error: 'int_' was not declared in this scope
>
> which seems fairly fundamental.

I certainly can only guess what happens there, but I think the checkout

svn checkout https://svn.boost.org/svn/boost/trunk/boost/spirit

creates a directory ./spirit. Could you try moving this into a subdirectory
boost, additionally. The final directory structure must be:

$SPIRIT21_ROOT/boost/spirit (/include/...)

And the -I $SPIRIT21_ROOT needs to be added to the compiler command line.
All spirit headers are included as

#include <boost/spirit/include/...>

that means you need to tell the compiler the base directory the
'boost/spirit/...' is in.

> Do I have the correct revision of Spirit? Any suggestions?

Seems to be the correct revision.

HTH
Regards Hartmut

Edward Grace

unread,
Jul 19, 2009, 3:55:07 PM7/19/09
to bo...@lists.boost.org
> creates a directory ./spirit. Could you try moving this into a
> subdirectory
> boost, additionally. The final directory structure must be:
>
> $SPIRIT21_ROOT/boost/spirit (/include/...)
>
> And the -I $SPIRIT21_ROOT needs to be added to the compiler command
> line.
> All spirit headers are included as
>
> #include <boost/spirit/include/...>
>
> that means you need to tell the compiler the base directory the
> 'boost/spirit/...' is in.

Bingo: Just a question of getting everything in the right place.

$ g++-4 -I spirit21_root -I $HOME/Desktop/boost_1_39_0 -o uint_parser
uint_parser.cpp
$ ./uint_parser
initializing input strings...
atoi: 1.42 [s]
strtol: 1.36 [s]
int_: 6.53 [s]

Clearly I need a faster laptop! ;-)

-ed
------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

Daniel Hulme

unread,
Jul 19, 2009, 6:48:53 PM7/19/09
to bo...@lists.boost.org
Hey, John. Your benchmark results make a very interesting addition to
the discussion. Perhaps I can clear something up for you:

On Sun, Jul 19, 2009 at 02:46:33PM +0100, John Bytheway wrote:
> The problem is that parse takes its first argument by reference, and
> va.begin() is a temporary. If I take a copy of va.begin() and pass that
> it works fine. I don't see how this compiled in MSVC (does
> string::begin() return a non-const reference?), but anyway.

MSVC allows binding temporaries to non-const reference arguments, as an
extension. It's sort of useful, but it's also sort of annoying -
sometimes both at once.

--
"He is strongly identified with rebels, you see, and very popular with
rabbles. They will follow him and he will fight to the last drop of
their blood." Chris Boucher, Blake's 7 D13 ‘Blake’
http://surreal.istic.org/ The Answer of the Oracle Is Always Death.

signature.asc

OvermindDL1

unread,
Jul 19, 2009, 7:09:18 PM7/19/09
to bo...@lists.boost.org
On Sun, Jul 19, 2009 at 1:15 PM, John Bytheway<jbythew...@gmail.com> wrote:
> Loop count:  10000000
> Parsing:  425/500
> original-custom:  1.6307
> xpressive:  116.992
> spirit-quick(static):  0.552722
> spirit-quick_new(threadsafe):  0.53429
> spirit-grammar(threadsafe/reusable):  0.680257

First of all, from what I read of the grammar, "425/500" is not a
valid 'price'. However, something like "0 425/500" would be, and from
what I read of all parsers, none would parse your format, so I bet if
you checked the return value of my parse function, the return would be
false, indicating it failed parsing. I would wager that the xpressive
probably is dieing because it does not know how to handle that value.

Edward Grace

unread,
Jul 19, 2009, 7:15:04 PM7/19/09
to bo...@lists.boost.org
Hi Joel,

> I tried a quick shot at it. There are compilation errors indeed.
> Please try to fix the errors first (*). You can get Spirit by getting
> the Boost trunk off SVN.

Ok, once I knew where to look it was easy to get sorted. I've placed
my example - based on your code - in the vault.

A typical example using a much smaller buffer (1000) vs (1000000) by
altering what you called MAX_ITERATION yields the following eye-
popping stats:

$ time ./ejg_uint_parser
initializing input strings...
Calibrating overhead......done
Timer overhead (t_c) ~= : 0.000195267
Jitter ~= : 2.02505e-14
qi_parse vs atoi : 1656.34 1661.63 1683.63% faster.
qi_parse vs strtol : 1521.71 1534.68 1547.75% faster.
strtol vs atoi : 4.17706 8.94977 10.1224% faster.
qi_parse vs qi_parse : -6.26613 -3.19258 -0.0182475% faster.

Checking that the results are correct...
atoi is behaving itself!
strtol is behaving itself!
qi is behaving itself!


All done!

real 7m37.575s
user 6m47.978s
sys 0m29.151s

N.B. The final timing of qi_parse against itself is zero percent
within the nominal precision. At first I thought the 1000% speedup
of qi_parse was a fake due to some compiler shenanigans. Now I don't
think so. I think it really is that much faster for small buffers!
Note that this timing experiment took ~6mins.

Using cycle.h:

This was all compiled with:

g++-4 -ansi -pedantic -DNDEBUG -O4 -I. -I spirit21_root -I $HOME/
Desktop/boost_1_39_0 -o ejg_uint_parser ejg_uint_parser.cpp

Where spirit21_root is the spirit library I downloaded earlier. It
passes the -ansi -pedantic test and is optimized to the max.


Repeating this with getticks() from cycle.h instead of the boost
based timer we get:

$ time ./ejg_uint_parser
initializing input strings...
Calibrating overhead......done
Timer overhead (t_c) ~= : 145.797
Jitter ~= : 5.31361
qi_parse vs atoi : 1672.05 1674.47 1677.3% faster.
qi_parse vs strtol : 1543.36 1547.38 1555.7% faster.
strtol vs atoi : 7.39392 7.79078 7.84302% faster.
qi_parse vs qi_parse : 0 0 0% faster.

Checking that the results are correct...
atoi is behaving itself!
strtol is behaving itself!
qi is behaving itself!


All done!

real 0m25.254s
user 0m22.124s
sys 0m2.496s

Same results - actually better since the experiment is quicker and
the 95th percentile range is therefore narrower. Obviously I'm
suspicious that something funny's going on - would you expect it to
be capable of being ~10x faster?

> (*) Also, please make sure you try it on Windows too. E.g. <sys/
> time.h>
> is non-standard, AFAIK. My main compiler is VC9. Your library is
> intended to be cross platform, right?

Can you try compiling ejg_uint_parser.cpp?

http://tinyurl.com/klh2hc

Like I say it's -ansi -pedantic, so 'gotta work'! ;-)

-ed

------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

OvermindDL1

unread,
Jul 19, 2009, 7:20:18 PM7/19/09
to bo...@lists.boost.org
On Sun, Jul 19, 2009 at 5:15 PM, Edward Grace<ej.g...@imperial.ac.uk> wrote:
> Can you try compiling ejg_uint_parser.cpp?
>
>   http://tinyurl.com/klh2hc

No, because your tinyurl link goes directly to the root of the vault,
not any file, and could not find the file when I placed the name in
the search. :)

Edward Grace

unread,
Jul 19, 2009, 7:24:46 PM7/19/09
to bo...@lists.boost.org

On 20 Jul 2009, at 00:20, OvermindDL1 wrote:

> On Sun, Jul 19, 2009 at 5:15 PM, Edward
> Grace<ej.g...@imperial.ac.uk> wrote:
>> Can you try compiling ejg_uint_parser.cpp?
>>
>> http://tinyurl.com/klh2hc
>
> No, because your tinyurl link goes directly to the root of the vault,
> not any file, and could not find the file when I placed the name in
> the search. :)

As the grate [sic] mind Homer would have said

"Doh"

Try this:

http://tinyurl.com/lro5ok

file "ejg_uint_parser.cpp"

-ed

------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

OvermindDL1

unread,
Jul 19, 2009, 8:13:03 PM7/19/09
to bo...@lists.boost.org
On Sun, Jul 19, 2009 at 5:24 PM, Edward Grace<ej.g...@imperial.ac.uk> wrote:
>
> On 20 Jul 2009, at 00:20, OvermindDL1 wrote:
>
>> On Sun, Jul 19, 2009 at 5:15 PM, Edward Grace<ej.g...@imperial.ac.uk>
>> wrote:
>>>
>>> Can you try compiling ejg_uint_parser.cpp?
>>>
>>>  http://tinyurl.com/klh2hc
>>
>> No, because your tinyurl link goes directly to the root of the vault,
>> not any file, and could not find the file when I placed the name in
>> the search.  :)
>
> As the grate [sic] mind Homer would have said
>
> "Doh"
>
> Try this:
>
> http://tinyurl.com/lro5ok
>
> file "ejg_uint_parser.cpp"

Okay, compiled the code, got this:
1>------ Build started: Project: ejg_uint_parser_timing,
Configuration: Release Win32 ------
1>Compiling...
1>ejg_uint_parser.cpp
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/statistics/statistics.hpp(417)
: error C2220: warning treated as error - no 'object' file generated
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/statistics/statistics.hpp(417)
: warning C4244: 'return' : conversion from 'double' to 'unsigned
int', possible loss of data
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/statistics/statistics.cpp(28)
: error C2039: 'ptr_fun' : is not a member of 'std'
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/statistics/statistics.cpp(28)
: error C2873: 'ptr_fun' : symbol cannot be used in a
using-declaration
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(273)
: warning C4003: not enough actual parameters for macro 'max'
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(384)
: warning C4003: not enough actual parameters for macro 'min'
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(385)
: warning C4003: not enough actual parameters for macro 'max'
1>using native typeof
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.hpp(1018)
: warning C4512: 'ejg::generic_timer<ticks>' : assignment operator
could not be generated
1> with
1> [
1> ticks=ticks
1> ]
1> .\ejg_uint_parser.cpp(133) : see reference to class template
instantiation 'ejg::generic_timer<ticks>' being compiled
1> with
1> [
1> ticks=ticks
1> ]
1>Build Time 0:09
1>Build log was saved at
"file://r:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\Release\BuildLog.htm"
1>ejg_uint_parser_timing - 3 error(s), 5 warning(s)


So yes, this is very much not usable for me, but there is your
buildlog anyway. :)

OvermindDL1

unread,
Jul 19, 2009, 8:13:54 PM7/19/09
to bo...@lists.boost.org

Er, and yes, this is with MSVC8(SP1) on Windows XP, using Boost Trunk
from about a week ago and your vault files.

OvermindDL1

unread,
Jul 19, 2009, 8:19:10 PM7/19/09
to bo...@lists.boost.org

The main error there, the ptr_fun, you did not include <functional>.

OvermindDL1

unread,
Jul 19, 2009, 8:32:43 PM7/19/09
to bo...@lists.boost.org

Sorry for the noise, but the only error I could not get rid of with
single-line edits to your files is:
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(117)
: error C2676: binary '-' : 'ticks' does not define this operator or a
conversion to a type acceptable to the predefined operator
1> R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(109)
: while compiling class template member function 'void
ejg::generic_timer<ticks>::calibrate_seconds(void)'


1> with
1> [
1> ticks=ticks
1> ]
1> .\ejg_uint_parser.cpp(133) : see reference to class template
instantiation 'ejg::generic_timer<ticks>' being compiled
1> with
1> [
1> ticks=ticks
1> ]

Edward Grace

unread,
Jul 19, 2009, 8:47:22 PM7/19/09
to bo...@lists.boost.org
> Okay, compiled the code, got this:
> 1>------ Build started: Project: ejg_uint_parser_timing,
> Configuration: Release Win32 ------
> 1>Compiling...
> 1>ejg_uint_parser.cpp
> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/statistics/statistics.hpp(417)
> : error C2220: warning treated as error - no 'object' file generated
> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/statistics/statistics.hpp(417)
> : warning C4244: 'return' : conversion from 'double' to 'unsigned
> int', possible loss of data

return std::ceil(-std::log(a)/std::log(2.0));

Ok, fair play, perhaps it's static_cast time.

> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/statistics/statistics.cpp(28)
> : error C2039: 'ptr_fun' : is not a member of 'std'
> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/statistics/statistics.cpp(28)
> : error C2873: 'ptr_fun' : symbol cannot be used in a
> using-declaration

It jolly well is a member of std::, perhaps I should include
<functional> then!

> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/timer.cpp(273)
> : warning C4003: not enough actual parameters for macro 'max'


WTF? What the hell's wrong with this?

time_raw_atom( _Operation f) {
ticks t0(0),t1(0),delta(std::numeric_limits<ticks>::max());

Ok. I bet MSVC (that's what you're using right) defines macros
called "min" and "max". I guess that's what happens when one sips
from the teat of the devil. A couple of undefs perhaps..

> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/timer.cpp(384)
> : warning C4003: not enough actual parameters for macro 'min'
> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/timer.cpp(385)
> : warning C4003: not enough actual parameters for macro 'max'
> 1>using native typeof

ticks max_global_ticks(std::numeric_limits<ticks>::min()),
min_global_ticks(std::numeric_limits<ticks>::max());

Ditto....


> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/timer.hpp(1018)
> : warning C4512: 'ejg::generic_timer<ticks>' : assignment operator
> could not be generated
> 1> with
> 1> [
> 1> ticks=ticks
> 1> ]
> 1> .\ejg_uint_parser.cpp(133) : see reference to class template
> instantiation 'ejg::generic_timer<ticks>' being compiled
> 1> with
> 1> [
> 1> ticks=ticks
> 1> ]
> 1>Build Time 0:09
> 1>Build log was saved at
> "file://r:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \Release\BuildLog.htm"
> 1>ejg_uint_parser_timing - 3 error(s), 5 warning(s)

Hmm, perhaps confusing the name of the template parameter with the type.

I don't need an assignment operator for ejg::generic_timer<?>. Looks
like it may be an oblique way of moaning about the const member
attribute.

> So yes, this is very much not usable for me,

Ouch.

> but there is your
> buildlog anyway. :)

Thanks.........


......I think. ;-)


Looking back at this email I think it's doable... Give me 10 mins
(then I really must go to bed!).

-ed


------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

OvermindDL1

unread,
Jul 19, 2009, 9:03:06 PM7/19/09
to bo...@lists.boost.org
On Sun, Jul 19, 2009 at 6:47 PM, Edward Grace<ej.g...@imperial.ac.uk> wrote:
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(273)
>> : warning C4003: not enough actual parameters for macro 'max'
>
>
> WTF?  What the hell's wrong with this?
>
>  time_raw_atom( _Operation f)  {
>    ticks t0(0),t1(0),delta(std::numeric_limits<ticks>::max());
>
> Ok.  I bet MSVC (that's what you're using right) defines macros called "min"
> and "max".  I guess that's what happens when one sips from the teat of the
> devil.  A couple of undefs perhaps..

Correct, some old VC headers define min/max for some godforsaken
reason. Anytime I use the words min/max in any of my files anywhere,
then at the top of the file, after the generic header includes I
always add:

#ifdef min
# undef min
#endif // min
#ifdef max
# undef max
#endif // max

And yea yea, I would like to use GCC to compile, but I currently have
sold my soul to the Visual Assist plugin for Visual Studio. If any
IDE out there with GCC support had anywhere near the capabilities of
Visual Assist (without Visual Assist, Eclipse is even better then VC),
I would switch in a heart-beat. Visual Assist just saves me on the
order of a monstrous amount of time, completely addicted by this
point.

Steven Watanabe

unread,
Jul 19, 2009, 9:07:19 PM7/19/09
to bo...@lists.boost.org
AMDG

Edward Grace wrote:
>> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(273)
>>
>> : warning C4003: not enough actual parameters for macro 'max'
>

> time_raw_atom( _Operation f) {
> ticks t0(0),t1(0),delta(std::numeric_limits<ticks>::max());
>
> Ok. I bet MSVC (that's what you're using right) defines macros called
> "min" and "max". I guess that's what happens when one sips from the
> teat of the devil. A couple of undefs perhaps..

Strictly speaking it's windows.h not msvc that #define's min and max.
See
http://www.boost.org/development/requirements.html#Design_and_Programming
for acceptable workarounds.

In Christ,
Steven Watanabe

Edward Grace

unread,
Jul 19, 2009, 9:10:06 PM7/19/09
to bo...@lists.boost.org
>
> Sorry for the noise, but the only error I could not get rid of with
> single-line edits to your files is:
> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/timer.cpp(117)
> : error C2676: binary '-' : 'ticks' does not define this operator or a
> conversion to a type acceptable to the predefined operator

The while statement?

chrono_start = chrono();
while (chrono_wall()-chrono_wall_start < chrono_wall_scale*4);
chrono_end = chrono();

Hmm. Depending on what the type of 'ticks' from cycle.h is (that's
what you're using right) that should just be a large integer type.
Perhaps try with the util::high_resolution_timer, which is of type
double().

Otherwise do you think the compiler is getting confused between the
name of the template parameter 'ticks' and the type 'ticks'?

-ed

------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

Edward Grace

unread,
Jul 19, 2009, 9:12:05 PM7/19/09
to bo...@lists.boost.org

On 20 Jul 2009, at 02:07, Steven Watanabe wrote:

> AMDG
>
> Edward Grace wrote:
>>> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
>>> \other_includes\ejg/timer.cpp(273)
>>>
>>> : warning C4003: not enough actual parameters for macro 'max'
>>
>> time_raw_atom( _Operation f) {
>> ticks t0(0),t1(0),delta(std::numeric_limits<ticks>::max());
>>
>> Ok. I bet MSVC (that's what you're using right) defines macros
>> called
>> "min" and "max". I guess that's what happens when one sips from the
>> teat of the devil. A couple of undefs perhaps..
>
> Strictly speaking it's windows.h not msvc that #define's min and max.
> See
> http://www.boost.org/development/
> requirements.html#Design_and_Programming
> for acceptable workarounds.

Thanks. Cap duly doffed.

-ed

-------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

Edward Grace

unread,
Jul 19, 2009, 9:12:44 PM7/19/09
to bo...@lists.boost.org
> And yea yea, I would like to use GCC to compile, but I currently have
> sold my soul to the Visual Assist plugin for Visual Studio. If any
> IDE

IDE? Whassat? What's wrong with........


....emacs? ;-)

(back on topic now)

-ed

Edward Grace

unread,
Jul 19, 2009, 9:49:03 PM7/19/09
to bo...@lists.boost.org

Hi OverminDL1,

> Sorry for the noise, but the only error I could not get rid of with
> single-line edits to your files is:
> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing
> \other_includes\ejg/timer.cpp(117)
> : error C2676: binary '-' : 'ticks' does not define this operator or a
> conversion to a type acceptable to the predefined operator
> 1> R:\Programming_Projects\Spirit_Price
> \ejg_uint_parser_timing\other_includes\ejg/timer.cpp(109)
> : while compiling class template member function 'void
> ejg::generic_timer<ticks>::calibrate_seconds(void)'

A bit of a stab in the dark, perhaps change the region around
timer.cpp(109) to

chrono_start = chrono();
while ( double( chrono_wall() - chrono_wall_start ) <
chrono_wall_scale*4.0);
chrono_end = chrono();

I'm now doubly confused as it appears to be complaining about the
return type of std::clock, (the default wall-clock timer). Maybe I
can get my hands on a windows machine and compiler tomorrow....

-ed

------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

Joel de Guzman

unread,
Jul 19, 2009, 11:51:51 PM7/19/09
to bo...@lists.boost.org
Edward Grace wrote:
>
> Hi OverminDL1,
>
>> Sorry for the noise, but the only error I could not get rid of with
>> single-line edits to your files is:
>> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(117)
>>
>> : error C2676: binary '-' : 'ticks' does not define this operator or a
>> conversion to a type acceptable to the predefined operator
>> 1>
>> R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(109)
>>
>> : while compiling class template member function 'void
>> ejg::generic_timer<ticks>::calibrate_seconds(void)'
>
> A bit of a stab in the dark, perhaps change the region around
> timer.cpp(109) to
>
> chrono_start = chrono();
> while ( double( chrono_wall() - chrono_wall_start ) <
> chrono_wall_scale*4.0);
> chrono_end = chrono();
>
> I'm now doubly confused as it appears to be complaining about the return
> type of std::clock, (the default wall-clock timer). Maybe I can get my
> hands on a windows machine and compiler tomorrow....

Edward, just a compliment (for now): what you are doing is cool!
I'm starting to be an eager supporter.

_______________________________________________

Joel de Guzman

unread,
Jul 20, 2009, 12:12:31 AM7/20/09
to bo...@lists.boost.org
Edward Grace wrote:

> N.B. The final timing of qi_parse against itself is zero percent within
> the nominal precision. At first I thought the 1000% speedup of qi_parse
> was a fake due to some compiler shenanigans. Now I don't think so. I
> think it really is that much faster for small buffers! Note that this
> timing experiment took ~6mins.

[...]

> Same results - actually better since the experiment is quicker and the
> 95th percentile range is therefore narrower. Obviously I'm suspicious
> that something funny's going on - would you expect it to be capable of
> being ~10x faster?

Interesting...

It seems that spatial locality strongly favors optimized Spirit
code very well -- best when the data structure can reside fully
in the cache. Try bumping the size incrementally and I expect a
big dip in performance at a certain point.

_______________________________________________

OvermindDL1

unread,
Jul 20, 2009, 4:23:20 AM7/20/09
to bo...@lists.boost.org
On Sun, Jul 19, 2009 at 7:12 PM, Edward Grace<ej.g...@imperial.ac.uk> wrote:
>> And yea yea, I would like to use GCC to compile, but I currently have
>> sold my soul to the Visual Assist plugin for Visual Studio. If any
>> IDE
>
> IDE? Whassat? What's wrong with........
>
>
> ....emacs? ;-)

Heh, believe me, it does no where near. Visual Assist parses out the
files, it know what are macros, templates, everything, it guesses most
of the code that I am writing for me, it literally puts in probably
80% of what I type, it is intelligent and very well made (once you
know how it thinks). Emacs could never compare as-is. Believe me,
once you use it for a month, you would be addicted. Most, if not all
major programming companies use it. :p


On Sun, Jul 19, 2009 at 7:12 PM, Edward Grace<ej.g...@imperial.ac.uk> wrote:
> (back on topic now)

Er, yes, right...

On Sun, Jul 19, 2009 at 7:10 PM, Edward Grace<ej.g...@imperial.ac.uk> wrote:
>> Sorry for the noise, but the only error I could not get rid of with
>> single-line edits to your files is:
>>
>> 1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(117)
>> : error C2676: binary '-' : 'ticks' does not define this operator or a
>> conversion to a type acceptable to the predefined operator
>

> The while statement?
>
> chrono_start = chrono();
> while (chrono_wall()-chrono_wall_start < chrono_wall_scale*4);
> chrono_end = chrono();
>

> Hmm. Depending on what the type of 'ticks' from cycle.h is (that's what


> you're using right) that should just be a large integer type. Perhaps try
> with the util::high_resolution_timer, which is of type double().

According to Visual Assist, ticks is of type LARGE_INTEGER, a union
type with 4 parts and a max size of 64-bits, it has no operator-
defined, hence you would need to reference an internal part, it looks
like QuadPart (like chrono_wall().QuadPart) would work, but that does
not fit into your design. I added this to the proper place in the
cycle.h file:
LARGE_INTEGER operator-(LARGE_INTEGER l, LARGE_INTEGER r)
{
LARGE_INTEGER res;
res.QuadPart = l.QuadPart - r.QuadPart;
return res;
}

Now it says:
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(117)

: error C2440: '<function-style-cast>' : cannot convert from
'LARGE_INTEGER' to 'double'
1> No user-defined-conversion operator available that can
perform this conversion, or the operator cannot be called


1> R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(109)
: while compiling class template member function 'void
ejg::generic_timer<ticks>::calibrate_seconds(void)'

1> with
1> [
1> ticks=ticks
1> ]
1> .\ejg_uint_parser.cpp(133) : see reference to class template
instantiation 'ejg::generic_timer<ticks>' being compiled
1> with
1> [
1> ticks=ticks
1> ]

1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(239)
: warning C4267: '=' : conversion from 'size_t' to 'unsigned int',
possible loss of data
1> .\ejg_uint_parser.cpp(154) : see reference to function
template instantiation 'void
ejg::generic_timer<ticks>::measure_percentage_speedup<void(__cdecl
*)(void),void(__cdecl *)(void)>(_OperationA,_OperationB,double
&,double &,double &)' being compiled
1> with
1> [
1> ticks=ticks,
1> _OperationA=void (__cdecl *)(void),
1> _OperationB=void (__cdecl *)(void)
1> ]
1>R:\Programming_Projects\Spirit_Price\ejg_uint_parser_timing\other_includes\ejg/timer.cpp(246)
: warning C4267: '=' : conversion from 'size_t' to 'unsigned int',
possible loss of data

So the union has no conversion to double, of course. Trying

What do you want me to do with util::high_resolution_timer?


On Sun, Jul 19, 2009 at 7:10 PM, Edward Grace<ej.g...@imperial.ac.uk> wrote:
> Otherwise do you think the compiler is getting confused between the name of
> the template parameter 'ticks' and the type 'ticks'?

Hmm, do not know, I never duplicate names like that so have not run into that...

On Sun, Jul 19, 2009 at 9:51 PM, Joel de
Guzman<jo...@boost-consulting.com> wrote:
> Edward, just a compliment (for now): what you are doing is cool!
> I'm starting to be an eager supporter.

I have to say that I like the design of your timer library as well,
looks to be very useful. :)

Edward Grace

unread,
Jul 20, 2009, 5:05:36 AM7/20/09
to bo...@lists.boost.org

Ahah. Perhaps that's why cycle.h has a macro called 'elapsed',
designed to take the difference between two numbers with these types.

Clearly this is going to be tougher than I thought. I originally
avoided making the list of stored time differences a concrete type
such as double, now it looks like I might have to. Otherwise it will
require sticking lots of extra cruft in as template arguments (a
function for taking differences of times for example).

> What do you want me to do with util::high_resolution_timer?

1) You need to make a chronometer function in global scope such as:

util::high_resolution_timer global_timer_object;

double boost_chrono() {
return global_timer_object.now();
}

Internal to the timing library it makes two calls to the chronometer
and uses the difference in the times, so it's important that
util::high_resolution_timer never gets reset. Since it's only double
precision this has subtle implications for long timings.

2) In the instantiation of ejg::generic_timer do replace the stuff
that looks like

ejg::generic_timer<ticks> timer(getticks);

with

ejg::generic_timer<double> timer(boost_chrono);

Everything else should then work from there. Let me know how that goes.

>> Otherwise do you think the compiler is getting confused between
>> the name of
>> the template parameter 'ticks' and the type 'ticks'?
>
> Hmm, do not know, I never duplicate names like that so have not run
> into that...

Let's assume it's ok for now...


> On Sun, Jul 19, 2009 at 9:51 PM, Joel de
> Guzman<jo...@boost-consulting.com> wrote:
>> Edward, just a compliment (for now): what you are doing is cool!
>> I'm starting to be an eager supporter.
>
> I have to say that I like the design of your timer library as well,
> looks to be very useful. :)

Thanks. There are (clearly) some wrinkles to iron out - but that's
why we are here.

-ed

------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

jon_...@agilent.com

unread,
Jul 20, 2009, 5:25:11 AM7/20/09
to bo...@lists.boost.org
hi there

any design patterns implementation in boost?

such as ,singleton,object factory,etc?

thanks
rui

Edouard A.

unread,
Jul 20, 2009, 5:33:48 AM7/20/09
to bo...@lists.boost.org
On Mon, 20 Jul 2009 17:25:11 +0800, <jon_...@agilent.com> wrote:

> any design patterns implementation in boost?
>
> such as ,singleton,object factory,etc?

If you are refering to the gang of 4 book, you have the flyweight design
pattern.

http://www.boost.org/doc/libs/1_39_0/libs/flyweight/doc/index.html

--

EA

Stewart, Robert

unread,
Jul 20, 2009, 9:18:00 AM7/20/09
to bo...@lists.boost.org
OvermindDL1 wrote:
>
> As stated, the numbers are basically hogwash until all three forms are
> all tested on the same hardware using the same compiler. I *might*
> have time tonight to work on the code that the others posted above to
> get it compilable, although it is rather irritating that they posted
> code that was incomplete, but meh.

I'm getting tired of reading your indirect insults of me. I already responded that I would post complete code if and when I could. I'm pleased to see you so excited to work on this now and to show that using Spirit may well be the ideal solution. I'm sorry for your irritation that more from me is not forthcoming, but I cannot do more just now. Please drop the negativity.

I posted my code in the most complete form I could for Eric's benefit, not so it would be a complete example and test suite for you and others could compile and run. *When* I have the opportunity, I will extract the code that exists in different files and libraries, and craft a custom version of the scaffolding necessary to make my Xpressive and custom code compile and which will reflect what I was actually running when I gave comparative results.

I tried posting a file with the test inputs to this list, but it made my message too large and was rejected. I didn't think it made sense to put such a file in the vault, so I have not put it there -- or anywhere -- as yet. Lacking any other concrete idea, I may post the file in the vault anyway. I will indicate as much when I do.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert

unread,
Jul 20, 2009, 9:19:32 AM7/20/09
to bo...@lists.boost.org
Eric Niebler wrote:
>
> Robert, can you please post your complete code so that we can
> actually
> have meaningful numbers to look at? Thanks.

I will do so as soon as I'm able.

OvermindDL1

unread,
Jul 20, 2009, 9:23:05 AM7/20/09
to bo...@lists.boost.org
On Mon, Jul 20, 2009 at 7:18 AM, Stewart, Robert <Robert....@sig.com> wrote:
> I'm getting tired of reading your indirect insults of me.  I already responded that I would post complete code if and when I could.  I'm pleased to see you so excited to work on this now and to show that using Spirit may well be the ideal solution.  I'm sorry for your irritation that more from me is not forthcoming, but I cannot do more just now.  Please drop the negativity.

No insults intended. Just on the other lists I frequent, posting
incomplete source-code is not allowed, and such 'hints' serve to
remind people of that. Habit is hard to drop on other lists since
that rule is so amazingly useful. :)


On Mon, Jul 20, 2009 at 7:18 AM, Stewart, Robert <Robert....@sig.com> wrote:
> I tried posting a file with the test inputs to this list, but it made my message too large and was rejected.  I didn't think it made sense to put such a file in the vault, so I have not put it there -- or anywhere -- as yet.  Lacking any other concrete idea, I may post the file in the vault anyway.  I will indicate as much when I do.

Posting large files to the list are fine, I have done so a few times,
it takes longer to get it accepted, but mine have always been
accepted. How long ago did you post it?

Thorsten Ottosen

unread,
Jul 20, 2009, 9:33:09 AM7/20/09
to bo...@lists.boost.org
OvermindDL1 skrev:

> On Mon, Jul 20, 2009 at 7:18 AM, Stewart, Robert <Robert....@sig.com> wrote:
>> I'm getting tired of reading your indirect insults of me. I already responded that I would post complete code if and when I could. I'm pleased to see you so excited to work on this now and to show that using Spirit may well be the ideal solution. I'm sorry for your irritation that more from me is not forthcoming, but I cannot do more just now. Please drop the negativity.
>
> No insults intended. Just on the other lists I frequent, posting
> incomplete source-code is not allowed, and such 'hints' serve to
> remind people of that. Habit is hard to drop on other lists since
> that rule is so amazingly useful. :)

Well, the code might not be yours to post, e.g. your employer might not
allow you to do that without permission.

Furthermore, one can ofte give very fast aswers if one does not need to
test code etc.

-Thorsten

Joel de Guzman

unread,
Jul 20, 2009, 9:49:31 AM7/20/09
to bo...@lists.boost.org
Thorsten Ottosen wrote:
> OvermindDL1 skrev:
>> On Mon, Jul 20, 2009 at 7:18 AM, Stewart, Robert
>> <Robert....@sig.com> wrote:
>>> I'm getting tired of reading your indirect insults of me. I already
>>> responded that I would post complete code if and when I could. I'm
>>> pleased to see you so excited to work on this now and to show that
>>> using Spirit may well be the ideal solution. I'm sorry for your
>>> irritation that more from me is not forthcoming, but I cannot do more
>>> just now. Please drop the negativity.
>>
>> No insults intended. Just on the other lists I frequent, posting
>> incomplete source-code is not allowed, and such 'hints' serve to
>> remind people of that. Habit is hard to drop on other lists since
>> that rule is so amazingly useful. :)
>
> Well, the code might not be yours to post, e.g. your employer might not
> allow you to do that without permission.
>
> Furthermore, one can ofte give very fast aswers if one does not need to
> test code etc.

Agreed, but Rob somehow presented a challenge when he said:

"The purpose of this exercise is to compare the code and performance,
so they must all perform the same task."

This implies that there's a code to compare to and benchmark
against. Also, it's rather frustrating to see posted benchmarks
without being able to really test them and scrutinize the code for
possible errors, etc.

_______________________________________________

Stewart, Robert

unread,
Jul 20, 2009, 9:51:33 AM7/20/09
to bo...@lists.boost.org
OvermindDL1 wrote:
> On Mon, Jul 20, 2009 at 7:18 AM, Stewart, Robert
> <Robert....@sig.com> wrote:
>
> > I tried posting a file with the test inputs to this list,
> but it made my message too large and was rejected. I didn't
> think it made sense to put such a file in the vault, so I
> have not put it there -- or anywhere -- as yet. Lacking any
> other concrete idea, I may post the file in the vault anyway.
> I will indicate as much when I do.
>
> Posting large files to the list are fine, I have done so a few times,
> it takes longer to get it accepted, but mine have always been
> accepted. How long ago did you post it?

As I said, it was rejected. I didn't suggest that the message is languishing in a moderation queue. Compressed, the file is over 300KiB.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert

unread,
Jul 20, 2009, 9:57:24 AM7/20/09
to bo...@lists.boost.org
Joel de Guzman wrote:

> Thorsten Ottosen wrote:
> >
> > Well, the code might not be yours to post, e.g. your employer
> > might not allow you to do that without permission.
> >
> > Furthermore, one can ofte give very fast aswers if one does
> > not need to test code etc.
>
> Agreed, but Rob somehow presented a challenge when he said:
>
> "The purpose of this exercise is to compare the code and
> performance, so they must all perform the same task."

As I recall the context, that was in answer to some questions about what Overmind had begun.

> This implies that there's a code to compare to and benchmark
> against. Also, it's rather frustrating to see posted benchmarks
> without being able to really test them and scrutinize the code
> for possible errors, etc.

Overmind was deviating from the original description and so I was showing that for *his work* to be comparable to what I had done and posted, it had to perform the same task. I'm sorry to have implied more.

I agree that little more can be done until I post complete examples or someone else manages to do so from what I did post.

_____
Rob Stewart robert....@sig.com
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Joel de Guzman

unread,
Jul 20, 2009, 9:58:01 AM7/20/09
to bo...@lists.boost.org
Stewart, Robert wrote:

> When* I have the opportunity, I will extract the code that exists in
different files and libraries, and craft a custom version of the
scaffolding necessary to make my Xpressive and custom code compile and
which will reflect what I was actually running when I gave comparative
results.
>

Thank you, Robert.

_______________________________________________

Zachary Turner

unread,
Jul 20, 2009, 10:28:43 AM7/20/09
to bo...@lists.boost.org
On Mon, Jul 20, 2009 at 4:33 AM, Edouard A.<edo...@fausse.info> wrote:
> On Mon, 20 Jul 2009 17:25:11 +0800, <jon_...@agilent.com> wrote:
>
>> any design patterns implementation in boost?
>>
>> such as ,singleton,object factory,etc?
>
> If you are refering to the gang of 4 book, you have the flyweight design
> pattern.
>
> http://www.boost.org/doc/libs/1_39_0/libs/flyweight/doc/index.html

And visitor (see boost::variant). Obviously iterator is implemented
by boost, and boost also has state machines implementing the State
pattern.

Edward Grace

unread,
Jul 20, 2009, 3:40:08 PM7/20/09
to bo...@lists.boost.org
>> chrono_start = chrono();
>> while ( double( chrono_wall() - chrono_wall_start ) <
>> chrono_wall_scale*4.0);
>> chrono_end = chrono();
>>
>> I'm now doubly confused as it appears to be complaining about the
>> return
>> type of std::clock, (the default wall-clock timer). Maybe I can
>> get my
>> hands on a windows machine and compiler tomorrow....
>
> Edward, just a compliment (for now): what you are doing is cool!
> I'm starting to be an eager supporter.

Always good to hear.... ;-)

After a mammoth effort and much code rejigging I've got it to not
only compile, but work on Windows with MSVC8! In fairness to the MS
compiler it did spot some subtle run-time errors that I was getting
away with just fine with g++. I've had to rip out parts that used
my home brew striding_iterator since there's no way to avoid
dereferencing one past the end of the end.

Similarly I've had to give up on keeping all the time deltas as
integer types in order to cope with the Windows .QuadPart approach.
If you refer back to the discussion I was having with OverminD1
(thanks a lot for your efforts) you'll see it was causing some grief
when trying to compile on Windows. As a consequence the timer
appears to be less sensitive, so may not pick out differences < 0.5%,
but frankly who cares? ;-)

Anyhow, enough rambling:

http://tinyurl.com/km9xlh

The new timing code (with a better PDF containing docs) is:

ejg-timer-0.0.3.tar.gz

Those of you watching in black and white need to set up MSVC and
compile example_timer.cpp. Everyone watching in colour need only do
the usual:

./configure; make; make install

voodo...

The uint_parser example that utilises the above is:

ejg_uint_parser_0_0_3.cpp

I wait with baited breath.

-ed


------------------------------------------------
"No more boom and bust." -- Dr. J. G. Brown, 1997

_______________________________________________

It is loading more messages.
0 new messages