help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: C++ / multiple instances / iostreams


From: Hans Aberg
Subject: Re: C++ / multiple instances / iostreams
Date: Sat, 24 Jul 2004 14:31:00 +0200

At 11:06 +0200 2004/07/24, Detlef Vollmann wrote:
>> But I have a memory of that some experts said that also such approaches
>> actually had an time overhead.
>See the Perfomance Report
> http://www.open-std.org/jtc1/sc22/open/n3646.pdf
>for a detailed description and analysis.
>The bottom line is, that as long as you don't throw exceptions,
>you have no time overhead.  On the first exception you actually
>throw, you get a huge overhead, as the table needs to be loaded.
>Later exceptions get a moderate overhead.

I saw that. I will have to look into it. It was a few years ago when I
followed the matter. It could be that it has moved beyond that state.

>> If I should take an example which is directly to the implementation of the
>> Bison C and C++ parsers, a question that pops up in this list from time to
>> time, then it the question of a dynamic parser stack:
>>
>> Under C, all struct data is POD, so it needs not to invoke any copy
>> constructors, so the whole stack can be re-copied in one go.
>Hmmm, if I look at my C++ skeleton for byacc, I don't see the need
>for copying the whole stack.  The only multi-element operation
>I use is on a reduction with a length > 1.  All others modifying
>operations are only single-element push and pop.

It is when the stack runs out of space. The current Bison parser C stack is
dynamic, and actually works that way.

>But in general, you're right: That multi-element erase needs to
>call the destructors for all the elements, while a C stack could
>just adjust the top pointer of the stack.

The current parser C stack doubles memory when it runs out, and I think it
halves when going below a quarter of its current allocation (usual
hysteresis). So merely adjusting pointers will not suffice.

The Bison parser stack used to have an initial fixed array allocation, but
that does not work under multithreading, so it should be removed by now, as
membranously C parser is thread-safe.

>The good news is, that if the destructors are actually NOPs,
>most optimizing compilers will eliminate the whole loop for
>the destructors, so in this case C and C++ produce effectively
>the same code.

No: I think it is likely to merely not invoke those destructors, but it
will probably still copy over element by element into the new stack
allocation. The C stack, on the other hand, does it all at once.

>In the case of copying a whole stack, in C you can just do a
>memcpy, while in C++ you need to loop over the elements and
>copy them one by one.  If the value type of the stack is a POD,
>the element cpoies can be memcpys, but to join those single
>memcpys into one overall memcpy is something that most optimizers
>don't do.

As I just said above. :-)

>Whether there is a measurable performance difference between the
>single memcpys and one big memcpy is another question...

There is probably a rather small difference. But thee main point is that
under C++, one accepts making such compromises, relative C. Just as C makes
such compromises relative assembly: C compilers can do a lot of
optimizations, but the cannot always do as good as in assembly by hand.
Most of the time, it is not worth replacing C by assembly though.

>Of cause, all these discussions assume that you use some template
>for the stack.

The obvious thing is to as default use the C++ standard containers. Those
that want to optimize can use whatever has the same class interface. So it
would not be difficult to use a C++ stack which copies over with a single
memcpy, but there would be no good way to tell when it should be used, and
it's probably not worth the effort from the point of performance.

  Hans Aberg






reply via email to

[Prev in Thread] Current Thread [Next in Thread]