Boost logo

Boost :

Subject: Re: [boost] Should Boost adopt pimpl/d-pointer as much as it can?
From: Domagoj Saric (domagoj.saric_at_[hidden])
Date: 2010-03-26 09:53:04

"Artyom" <artyomtnk_at_[hidden]> wrote in message
> I think that Boost should adopt as policy:
> 1) All implementation related code **should** be put in sources.

I would agree, because most non-header-only libraries can probably AFAIK be
easily converted to a header only simply by treating .cpp files as .inl/.ipp
files that get included at the bottom of the header if a configuration
option/macro specifies that a header only library is wanted (of course special
care needs to be taken for static objects, static/inline functions and
private/anonymous namespaces).

> 2) Any non-template based class should have opaque/d/pimpl pointer in its
> body.

I would most strongly disagree. The reason is, of course, efficiency. Let's take
for example memory mapped files. You just want to map a file into memory and get
a pair of pointers that mark the mapped memory range. For that boost gives us
the iostreams::mapped_file class. Then you see that unfortunately this class
uses the pimpl idiom, I really do not know why because, on Windows, the pointer
to the mapped file view is at the same time also the handle to the view that
also internaly holds the handle to the file mapping and the file being mapped
(as it clearly stated on MSDN) so the only thing you need to hold as a member
variable is a plain old simple void/char pointer...Additionaly you can query the
size to have the pointer pair and a container interface. Even if you had to hold
two additional handles it still makes no sense to use a pimpl because handles
are also just plain pointers.
But, the mentioned iostreams::mapped_file class uses a shared_ptr<> (even though
a scoped_ptr would be enough) with all its nice and insignificant virtual
functions, RTTI, double memory allocations, locking and indirect deleting.

Before someone raises the "you are a premature optimizer and therefore evil"
and/or the "you are doing disk access and going into kernel, who cares about
pimpl overhead" sign posts let us look at the real world results that show where
does this 'by the book ignoring of efficiency until a profiler says otherwise'
take us.

To be correct, the pimp+shared_ptr<> are not the only cause for the following
results. The mentioned class is plaged by various other unnecessary
C++-ifications (e.g. std::string usage when in fact all the underlying OS
implementations work with plain char pointers).

Anyways, to measure the space and time overhead of boost::iostreams::mapped_file
(from boost 1.40) class I've used a custom created class (WinMemoryMappedFile,
included in the attachment) that does just what I need (map a file, throw on
error, and give me a begin and an end pointer) without all the shared_ptr,
std::string, std::ios_base 'goodies'.


- an empty project with an empty main function:
        45 056 bytes (yes MSVC CRT is 'evil')

- void main(...)
    WinMemoryMappedFile f( "C:/boot.ini" );
    std::ptrdiff_t size( f.end() - f.begin() );
        46 080 bytes

- void main(...)
    boost::iostreams::mapped_file f( "C:/boot.ini" );
    std::ptrdiff_t size( f.end() - f.begin() );
        58 880 bytes get the result of calling 6 different OS API calls and to throw an
exception boost::iostreams::mapped_file brings in >13824< bytes of code (that's
~13 times more than WinMemoryMappedFile)...

Spinning the above two lines 100000 times takes:
 - WinMemoryMappedFile ~1.71 seconds
- boost::iostreams::mapped_file ~1.96 seconds
...that's about 15% slower/longer...

I'd say all this quite clearly:
- shows that avoiding 'premature optimization' is actually 'causing premature
- says no to forcing pimpls or any other type of abstraction or 'C++-ification'
"on people" if it is not actually necessary...

Otherwise I'might begin to understand Linus when he says "Quite frankly, even if
the choice of C were to do *nothing* but keep the C++ programmers out, that in
itself would be a huge reason to use C." (and I really do _not_ like C).

In this particular case, for me the choice was simply not to use boost but my
own implementation, which is said IMO...

> These are results of compilation times with gcc-4.3 (seconds):
> -O0 -O2 -O3 -O2+link
> asio 2.56 4.65 4.96 4.75
> pimpl 0.59 0.85 0.89 0.94
> diff *4.3 *5.5 *5.6 *5.05

Did you perhaps try to just move non-templated implementation into .cpps,
without pimpling?

> For me, compilation of components based on Asio is total nightmare
> because of unacceptable compilation times.

When using precompiled headers (which is always ;) I do not notice any compile
time performance hit from just including a boost header (except when doing a
rebuild of course :), using it however is a different thing of course if it is
template based (but then you cannot pimpl it anyway)...

> Another issue is executable size. I had took same echo sever
> placed in 10 object compiled under different namespaces
> once I did it with Boost.Asio and then I did it with pimpl-ed Asio.
> Result (liked executable size with gcc-4.3):
> Build Size (-Os stripped)
> Asio: 245K
> Pimpl: 190K

Hmm...this is if your compiler and linker are seriously 'broken' or
'weak' at throwing out unwanted things/merging same functions...If gcc has a
'link time code generation' option try using it...
Using a pimpl based implementation should always give a slower and larger code
(even if completely insignificantly) simply because of its overhead....

> Conclusions:
> ============
> makes executable sizes much bigger (this
> is especially relevant for embedded systems).

Actually, with a proper linker, pimpling makes your code bigger...

> Should Boost wellcome pimpled libraries more? I think yes.

Only if provided as optional wrappers around otherwise 'lean' libraries...

> 2. It would allow to provide changes easily without breaking
> compatibility (even would allow to provide backward ABI compatibility)

Qt uses pimpling for just about everything, the result (not nearly only because
of that of course): it has grown to an unbelievably humongous bloated monster
that compiles (for hours) to a size of several server OS kernels...

"What Huxley teaches is that in the age of advanced technology, spiritual
devastation is more likely to come from an enemy with a smiling face than from
one whose countenance exudes suspicion and hate."
Neil Postman
begin 666 WinMemoryMappedFile.hpp
M+2TM+2TM+2TM+2TM+2TM+2TM+2T-"B\O+PT*+R\O($-O<'ER:6=H=" H8RD@
M,C Q,"X_at_1&]M86=O:B!387)I8RX-"B\O+PT*+R\O+R\O+R\O+R\O+R\O+R\O
M<&5D1FEL95]H<'!?7S=",T%&-#(V7SDP1#)?-$1!15]!,#8P7T0X.30T1C T
M="YH<' B#0HC:6YC;'5D92 B8F]O<W0O;F]N8V]P>6%B;&4N:'!P(@T*(VEN
M+2TM+2TM+2TM#0H-"F-L87-S(%=I;DUE;6]R>4UA<'!E9$9I;&4-"B @(" Z
M#0H@(" @<'5B;&EC("!B;V]S=#HZ:71E<F%T;W)?<F%N9V4\=6YS:6=N960@
M8VAA<B J/BP-"B @("!P<FEV871E(&)O;W-T.CIN;VYC;W!Y86)L90T*>PT*
M<'5B;&EC._at_T*(" @(%=I;DUE;6]R>4UA<'!E9$9I;&4H(&-H87(@8V]N<W0@
M*B!F:6QE3F%M92 I.PT*(" @('Y7:6Y-96UO<GE-87!P961&:6QE*"D[#0H-
M"@T*<')I=F%T93H-"B @("!I=&5R871O<E]R86YG92 F(&%D=F%N8V5?8F5G
M:6XH(&1I9F9E<F5N8V5?='EP92 I.PT*(" @(&ET97)A=&]R7W)A;F=E("8@
M92@@8VAA<B!C;VYS=" J(&-O;G-T(&9I;&5.86UE("D-"GL-"B @("!"3T]3
M5%]!4U-%4E0H(&9I;&5.86UE("D[#0H-"B @("!(04Y$3$4_at_8V]N<W0_at_9FEL
M95]H86YD;&4-"B @(" H#0H@(" @(" @(#HZ0W)E871E1FEL94$-"B @(" @
M(" @* T*(" @(" @(" @(" @9FEL94YA;64L($=%3D5224-?4D5!1"!\($=%
M($9)3$5?05144DE"551%7U1%35!/4D%262P@, T*(" @(" @(" I#0H@(" @
M*3L-"B @("!"3T]35%]!4U-%4E0H("@@9FEL95]H86YD;&4@/3T_at_24Y604Q)
M1%](04Y$3$5?5D%,544@*2!\?" H(#HZ1V5T3&%S=$5R<F]R*"D@/3T_at_3D]?
M15)23U(@*2!\?" H(#HZ1V5T3&%S=$5R<F]R*"D@/3T_at_15)23U)?04Q214%$
M65]%6$E35%,@*2 I.PT*#0H@(" @+R\@270@:7,@)T]+)R!T;R!S96YD(&YU
M('=I;&P-"B @(" O+R!S:6UP;'D_at_9F%I;"DL('1H:7,@<VEM<&QI9FEE<R!E
M<G)O<B!H86YD;&EN9R H:70@:7,@96YO=6=H('1O(&=O('1H<F]U9V_at_-"B @
M(" O+R!A;&P@=&AE(&QO9VEC+"!I;G-P96-T('1H92!F:6YA;"!R97-U;'0@
M86YD('1H96X@=&AR;W<@;VX_at_97)R;W(I+@T*#0H@(" @+R\@0W)E871E1FEL
M9"!I;G!U="!B=70@;VYL>2!I9_at_T*(" @("\O('1H92!S:7IE('!A<F%M971E
M;W)E(&%L<V\-"B @(" O+R!F86EL(&5V96X@:68_at_9FEL95]H86YD;&4@/3T@
M24Y604Q)1%](04Y$3$5?5D%,544L(&IU<W0_at_87,@:7,@9&5S:7)E9"X-"B @
M("!(04Y$3$4_at_8V]N<W0_at_9FEL95]M87!P:6YG7VAA;F1L90T*(" @("@-"B @
M(" @(" @.CI#<F5A=&5&:6QE36%P<&EN9R@@9FEL95]H86YD;&4L(# L(%!!
M1T5?4D5!1%=2251%+" P+" P+" P("D-"B @(" I.PT*(" @($)/3U-47T%3
M4T525 T*(" @("@-"B @(" @(" @* T*(" @(" @(" @(" @(69I;&5?;6%P
M<&EN9U]H86YD;&4@)B8-"B @(" @(" @(" @("@-"B @(" @(" @(" @(" @
M(" H(" @9FEL95]H86YD;&4@(3T_at_24Y604Q)1%](04Y$3$5?5D%,544@*2!\
M? T*(" @(" @(" @(" @(" @("@@*"!F:6QE7VAA;F1L92 ]/2!)3E9!3$E$
M7TA!3D1,15]604Q512 I("8F("@@.CI'971,87-T17)R;W(H*2 ]/2!%4E)/
M4E])3E9!3$E$7U!!4D%-151%4B I("D-"B @(" @(" @(" @("D-"B @(" @
M(" @*0T*(" @(" @(" @(" @?'P-"B @(" @(" @*" Z.D=E=$QA<W1%<G)O
M<B_at_I(#T]($Y/7T524D]2("D-"B @(" I.PT*#0H@(" @:71E<F%T;W(@8V]N
M<W0@=FEE=U]S=&%R="@@<W1A=&EC7V-A<W0\:71E<F%T;W(^*" Z.DUA<%9I
M0T-%4U,L(# L(# L(# @*2 I("D[#0H@(" @#0H@(" @1%=/4D0_at_8V]N<W0@
M9FEL95]S:7IE*" Z.D=E=$9I;&53:7IE*"!F:6QE7VAA;F1L92P@," I("D[
M#0H@(" @0D]/4U1?05-315)4*" H(&9I;&5?<VEZ92 A/2 M,2 I('Q\("@@
M9FEL95]H86YD;&4@/3T_at_24Y604Q)1%](04Y$3$5?5D%,544@*2!\?" H(#HZ
M1V5T3&%S=$5R<F]R*"D@/3T_at_3D]?15)23U(@*2 I.PT*#0H@(" @+R\@26UP
M;&5M96YT871I;VX@;F]T93H-"B @(" O+R!-87!P960@=FEE=W,@:&]L9"!I
M;R!W92!D;PT*(" @("\O(&YO="!N965D(&AO;&0O<W1O<F4@=&AE;2!O=7)S
M96QV97,Z#0H@(" @+R\@:'1T<#HO+VUS9&XN;6EC<F]S;V9T+F-O;2]E;BUU
M<R]L:6)R87)Y+V%A,S8V-3,W*%93+C_at_U*2YA<W!X#0H@(" @+R\@(" @(" @
M(" @(" @(" @(" @(" @(" @(" @(" @(" @(" @(" @*#(V+C S+C(P,3 N
M*2 H1&]M86=O:B!387)I8RD-"B @("!"3T]35%]615))1EDH(#HZ0VQO<V5(
M86YD;&4H(&9I;&5?:&%N9&QE(" @(" @(" @*2!\?" H(&9I;&5?:&%N9&QE
M(#T]($E.5D%,241?2$%.1$Q%7U9!3%5%("D@*3L-"B @("!"3T]35%]615))
M1EDH(#HZ0VQO<V5(86YD;&4H(&9I;&5?;6%P<&EN9U]H86YD;&4@*2!\?" A
M9FEL95]M87!P:6YG7VAA;F1L92 @(" @(" @(" @(" @(" @(" @*3L-"@T*
M(" @(&EF("@@(79I97=?<W1A<G0@*0T*(" @(" @("!T:')O=R!S=&0Z.F5X
M(" @('1Y<&5D968@='EP92!M>5]R86YG93L-"B @("!M>5]R86YG93HZ;W!E
M<F%T;W(@/2 H(&UY7W)A;F=E*"!V:65W7W-T87)T+"!V:65W7W-T87)T("L@
M:6QE.CI^5VEN365M;W)Y36%P<&5D1FEL92_at_I#0I[#0H@(" @0D]/4U1?5D52
M2499*" Z.E5N;6%P5FEE=T]F1FEL92@@8F5G:6XH*2 I("D[#0I]#0H-"@T*
M+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2T-"B-E;F1I9B O
=+R!7:6Y-96UO<GE-87!P961&:6QE7VAP< T*#0H`

Boost list run by bdawes at, gregod at, cpdaniel at, john at