Boost logo

Boost Users :

Subject: Re: [Boost-users] sizeof(boost::fusion:map)
From: alfC (alfredo.correa_at_[hidden])
Date: 2010-11-06 08:33:08


On Nov 6, 5:17 am, Christopher Schmidt <mr.chr.schm..._at_[hidden]>
wrote:
> alfC schrieb:
>
>
>
>
>
> > On Nov 5, 9:49 pm, Joel de Guzman <j..._at_[hidden]> wrote:
> >> On 11/6/2010 7:56 AM, Christopher Schmidt wrote:
>
> >>> Christopher Schmidt schrieb:
> >>>> Robert Lupton the Good schrieb:
> >>>>> I was very excited to find the boost::fusion library, expecting that I could use it to implement structs with introspection.  I still think I can, but I was disappointed to see that I'm paying a size penalty. I'd have expected all the book-keeping to be handled at compile time.
>
> >>>>> The following code prints
> >>>>>    sizeof(Foo) = 12 sizeof(FooS) = 4
> >>>>> with g++ 4.2 or 4.4 on an os/x 10.6 or Centos box.
>
> >>>>> Here Foo is
> >>>>>    boost::fusion::map<boost::fusion::pair<Name, int>  >
>
> >>>> [snip]
>
> >>>> I have no idea why there is that space overhead. This problem is not
> >>>> fusion specific, though.
>
> >>>> #include<iostream>
> >>>> struct X{};
> >>>> struct A:X{int i;};
> >>>> struct B:X{A a;};
> >>>> int main()
> >>>> {std::cout<<  sizeof(A)<<  " "<<  sizeof(B)<<  std::endl;}
>
> >>>> When compiled with gcc 4.5.1 i686-pc-mingw32 and -O2, the output is "4
> >>>> 8". When compiled with MSVC 2010 (x86) and /O2, "4 4" is printed.
>
> >>>> -Christopher
>
> >>> I think gcc is correct. There are two distinct instances of X in B, and
> >>> those may not have the same address. That's why there is that 4 byte
> >>> displacement.
> >>> It is pretty much the same in Fusion. All inbuilt sequences and the
> >>> vector data storage share a common base class - fusion::sequence_root -
> >>> that's where the 4 resp. 8 bytes come from.
>
> >> Good analysis, Christopher. We should do something about this.
> >> sequence_root is only there for easy tag detection. There should
> >> be better way.
>
> > Joel,
>
> > If I am not wrong: this is related to a question I asked some weeks
> > ago. When I was surprised (disappointed?) to find that
> > fusion::vector<double, double, double> has a memory layout different
> > than double[3] (or boost::array<double,3>). I didn't look at the
> > 'sizeof' then but know that Robert mentions it I tried:
>
> > std::clog << sizeof(double) << std::endl;
> > std::clog << sizeof(vector<double, double, double>) << std::endl;
> > std::clog << sizeof(boost::array<double, 3>) << std::endl;
>
> > which in my platform emits:
>
> > 8
> > 28
> > 24
>
> > It would be interesting to know what does Boost.fusion stores in the
> > extra bytes and why on earth neither the size nor the memory layout is
> > the same as the contained data. It seems that the inconsistency on the
> > size raises more eyebrows than the unexpected memory layout.
>
> Nothing is stored in those 4 additional bytes.
> As I said above one additional byte is added by the compiler to the
> 3*sizeof(double) bytes so one is able to distinguish between the two
> instances of a common base class (fusion::sequence_root) of the vector
> (fusion::vector<double, double, double>) and the internal vector data
> storage (fusion::vector3<double, double, double>). To get size and
> alignment right this one byte actually emits a 4-byte overhead on your
> compiler.

Isn't something called Empty Base Optimization that helps with this
problem? (not sure if it applies here).

So there is no way around it? (unless the internal design is changed?)

What do you mean by my compiler? are there compiler options that can
optimize these? (I use gcc 4.4)

>
> -Christopher
>
> _______________________________________________
> Boost-users mailing list
> Boost-us..._at_[hidden]http://lists.boost.org/mailman/listinfo.cgi/boost-users


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net