Boost logo

Boost :

From: Joel de Guzman (joel_at_[hidden])
Date: 2006-12-17 17:12:21


Gennadiy Rozental wrote:
> "Joel de Guzman" <joel_at_[hidden]> wrote in message
> news:elv64c$qao$1_at_sea.gmane.org...
>> Gennadiy Rozental wrote:
>>> "David Abrahams" <dave_at_[hidden]> wrote in message
>>> news:87lkl93hlx.fsf_at_pereiro.luannocracy.com...
>>>> "Gennadiy Rozental" <gennadiy.rozental_at_[hidden]> writes:
>>>>
>>>>> This is not clear cut. I do not see in theory why any boost::variant
>>>>> based
>>>>> algorithm couldn't be optimized to almost the same code (module type
>>>>> switching). On the other hand excessive usage of tuples will cause
>>>>> appropriate code bloat, eventually leading to code slow down.
>>>> Not clear cut at all. When operating on a sequence where all the
>>>> types are different, the version with variant will be both slower and
>>>> larger.
>>> I love these performance "estimations"
>>>
>>> Do you have any numbers to sustain this?
>> Yes. Dan posted some in my answer to your post in the fusion
>> review sometime ago. You must've missed it. Here it is again
>> (see attached). Here's the link to Dan's post:
>>
>> http://tinyurl.com/yawqs3
>>
>> You must've missed it.
>
> I did not have resources at the time to analize your test.
>
>> We see speed differences as much as 20X. In addition to speed,
>> notice the variant size too.
>
> It does indeed looks like the test in hand indicate that for the more or
> less trivial actors most (not all BTW) are able to optimize fusion version
> much better. Plus all the type switching and loop iteration is starting to
> play the role.
>
> But let's get to the problem at hand: output operation. I changed
> accumulator implementation in your test to still very trivial one like this:
>
> struct accumulator {
> accumulator( std::ostream& os )
> : m_os( os ) {}
>
> template<typename T>
> void operator()(T const &t) const
> {
> this->m_os << t << ',';
> }
>
> std::ostream& m_os;
> };
>
> (and the rest of the test appropriately)
>
> See attached files.
>
> When I used onullstream as ostream in test the fusion based version shows
> stable results of only 20% better performance advantage. onullstream does
> nothing whatsoever, just some virtual calls.
> When I used std::cerr instead, both fusion and boost::variant version show
> exactly the same performance (maybe 1-2% difference, but it depends on how
> long you run the test).
> boost::variant based version used offline implementation of test routine and
> test executable size doesn't grow that much when number of calls increases
> fusion based used inline implementation of test routine and test executable
> size grows faster.
>
> So my concluding is that I may use either version for the task at hand.
> Actual decision will depend on other factors but performance. If I keep the
> values in vectors of variant anyway I obviously prefer variant based
> version. If I need to create these collection on a fly I may opt to stick
> with the fusion. There maybe some other reasoning.

You should state clearly that in your tests, you are not testing the
abstraction penalty of fusion/variant because the timings will
heavily reflect the stream I/O, not the fusion/variant interfaces.
IOTW, what you are actually testing is the speed of I/O operations
(even if it is an empty virtual function-- in which case you are
testing the virtual function call penalty).

You obviously prefer variant, which is perfectly ok. As you
say, actual decision will depend on other factors than performance.
I actually agree with you on that. I myself use containers of
variants too. In some uses, it is the perfect choice.

Regards,

-- 
Joel de Guzman
http://www.boost-consulting.com
http://spirit.sf.net

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