Re: [boost] serialization performance

bwood <brass@mailvault.com> writes:
Hi, Dave,
Hi Brian
I work on www.webEbenezer.net. I noticed today that Robert Ramey said "So far so good" regarding some performance tests he is doing. You might want to encourage him to consider some of the competition as far as performance.
You should probably be doing that, actually ;-) I'm helpfully cross-posting this reply to the Boost developers' list, but next time, please do it yourself so that you get "in the mix" there. Having these kinds of reports in the public record, and having people like you involved in the ensuing discussion, are crucial for the Boost process. Thanks again for writing.
Some recent tests I've done that compare Ebenezer Enterprises and Boost.serialization's performance show the Boost.serialization approach to be 7 to 9 times slower than the Ebenezer Enterprises approach. I'm using Linux 2.6.12, gcc 4.0.2 (with -O3) and a Boost.serialization library from the release tree. A test that compared the times to serialize/send a list<int> took 7.4 times longer with Boost than Ebenezer. I timed the following Boost: oArch & lst; // oArch is a binary_oarchive
Ebenezer: msgs.Send(buffer, lst); // In order to compare apples to apples, // I removed a section of code at the end
// of the Send function that flushes the buffer.
In a second test I added a deque of int... Boost: oArch & lst; oArch & dq; // std::deque<int> dq;
Ebenezer: msgs.Send(buffer, lst, dq);
In this case Boost took 9.1 times longer than Ebenezer Enterprises approach. If you want to run these tests with other compilers I think that would be helpful. I've been warned not to put too much emphasis on numbers from gcc.
Regards, Brian Wood
-- Dave Abrahams Boost Consulting www.boost-consulting.com

I work on www.webEbenezer.net. I noticed today that Robert Ramey said "So far so good" regarding some performance tests he is doing. You might want to encourage him to consider some of the competition as far as performance.
Some recent tests I've done that compare Ebenezer Enterprises and Boost.serialization's performance show the Boost.serialization approach to be 7 to 9 times slower than the Ebenezer Enterprises approach. I'm using Linux 2.6.12, gcc 4.0.2 (with -O3) and a Boost.serialization library from the release tree. A test that compared the times to serialize/send a list<int> took 7.4 times longer with Boost than Ebenezer. I timed the following Boost: oArch & lst; // oArch is a binary_oarchive
Ebenezer: msgs.Send(buffer, lst); // In order to compare apples to apples, // I removed a section of code at the end
// of the Send function that flushes the buffer.
In a second test I added a deque of int... Boost: oArch & lst; oArch & dq; // std::deque<int> dq;
Ebenezer: msgs.Send(buffer, lst, dq);
In this case Boost took 9.1 times longer than Ebenezer Enterprises approach. If you want to run these tests with other compilers I think that would be helpful. I've been warned not to put too much emphasis on numbers from gcc.
I've written a test program to compare the time required by boost serialization to the time required by using stream i/o to do a similar operation. I've only used VC 7.1 (release mode) and my focus has been to try to determine how much overhead the serialization system adds compared to the alternative of not using it. The test consists for saving/loading 1000 instances of a class which includes all primitive types (? about 20 members including strings). Times are calculated by dividing the total time by 1000 to give ms / operaton. These preliminary results don't raise any major red flags. I'm still working on this in my spare time. A couple of problems are: a) timings are too crude. b) I need to make a standard library test which writes/read binary data. This is interesting for comparison purposes, though I doubt many people actually use output/input streams in this way. c) I'm aware that there are couple of opportunities for improved performance in the archive implementation. d)I really want to get profile data from this (improved) test. I'm having some problems because not all plaforms support profiling and I'm having some problems figuring out how to work into bjam in the way I want. e)If I've got nothing else to do, I might want to enhance this with tests of some stl collections. Note that the compiled version of the attached program using the static library of the serialization library and the DLL version of the VC C++ runtime library is 268K. Given what we're serializing to three different archives, including xml, this seems like a very reasonable number to me. Below are a couple of test runs. Robert Ramey standard library write to file 0.047ms read from file 0.016ms binary_archives save archive 0ms save archive through pointer 0.015ms load archive 0.016ms load archive through pointer 0.016ms text_archives save archive 0.062ms save archive through pointer 0.047ms load archive 0.046ms load archive through pointer 0.079ms xml_archives save archive 0.11ms save archive through pointer 0.156ms load archive 0.187ms load archive through pointer 0.203ms *** No errors detected Running 1 test case... standard library write to file 0.062ms read from file 0.016ms binary_archives save archive 0.016ms save archive through pointer 0.015ms load archive 0.016ms load archive through pointer 0.031ms text_archives save archive 0.094ms save archive through pointer 0.078ms load archive 0.078ms load archive through pointer 0.093ms xml_archives save archive 0.125ms save archive through pointer 0.141ms load archive 0.172ms load archive through pointer 0.219ms *** No errors detected Press any key to continue Running 1 test case... standard library write to file 0.047ms read from file 0ms binary_archives save archive 0.016ms save archive through pointer 0.015ms load archive 0ms load archive through pointer 0.016ms text_archives save archive 0.063ms save archive through pointer 0.062ms load archive 0.063ms load archive through pointer 0.093ms xml_archives save archive 0.125ms save archive through pointer 0.157ms load archive 0.187ms load archive through pointer 0.219ms *** No errors detected Press any key to continue begin 666 test_overhead.cpp M+R\O+R\O+R\O,2\O+R\O+R\O+S(O+R\O+R\O+R\S+R\O+R\O+R\O-"\O+R\O M+R\O+S4O+R\O+R\O+R\V+R\O+R\O+R\O-R\O+R\O+R\O+S@-"B\O('1E<W1? M;W9E<FAE860N8W!P#0H-"B\O("A#*2!#;W!Y<FEG:'0@,C P-2!2;V)E<G0@ M4F%M97D@+2!H='1P.B\O=W=W+G)R<V0N8V]M("X@#0HO+R!5<V4L(&UO9&EF M:6-A=&EO;B!A;F0@9&ES=')I8G5T:6]N(&ES('-U8FIE8W0@=&\@=&AE($)O M;W-T(%-O9G1W87)E#0HO+R!,:6-E;G-E+"!697)S:6]N(#$N,"X@*%-E92!A M8V-O;7!A;GEI;F<@9FEL92!,24-%3E-%7S%?,"YT>'0@;W(@8V]P>2!A= T* M+R\@:'1T<#HO+W=W=RYB;V]S="YO<F<O3$E#14Y315\Q7S N='AT*0T*#0HO M+R!S:&]U;&0@<&%S<R!C;VUP:6QA=&EO;B!A;F0@97AE8W5T:6]N#0H-"B\O M(&EN=F]K92!H96%D97(@9F]R(&$@8W5S=&]M(&%R8VAI=F4@=&5S="X-"@T* M(VEN8VQU9&4@/&9S=')E86T^#0HC:6YC;'5D92 \:6]S=')E86T^#0H-"B-I M;F-L=61E(#QC<W1D:6\^("\O(')E;6]V90T*(VEN8VQU9&4@/&)O;W-T+V-O M;F9I9RYH<' ^#0H-"B-I9B!D969I;F5D*$)/3U-47TY/7U-41$-?3D%-15-0 M04-%*0T*;F%M97-P86-E('-T9'L@#0H@(" @=7-I;F<@.CIR96UO=F4[#0I] M#0HC96YD:68-"@T*(VEN8VQU9&4@/&)O;W-T+W1I;65R+FAP<#X-"@T*(VEN M8VQU9&4@(G1E<W1?=&]O;',N:'!P(@T*(VEN8VQU9&4@/&)O;W-T+V%R8VAI M=F4O8FEN87)Y7V]A<F-H:79E+FAP<#X-"B-I;F-L=61E(#QB;V]S="]A<F-H M:79E+V)I;F%R>5]I87)C:&EV92YH<' ^#0HC:6YC;'5D92 \8F]O<W0O87)C M:&EV92]T97AT7V]A<F-H:79E+FAP<#X-"B-I;F-L=61E(#QB;V]S="]A<F-H M:79E+W1E>'1?:6%R8VAI=F4N:'!P/@T*(VEN8VQU9&4@/&)O;W-T+V%R8VAI M=F4O>&UL7V]A<F-H:79E+FAP<#X-"B-I;F-L=61E(#QB;V]S="]A<F-H:79E M+WAM;%]I87)C:&EV92YH<' ^#0H-"B-I;F-L=61E(#QB;V]S="]S97)I86QI M>F%T:6]N+VYV<"YH<' ^#0H-"B-I;F-L=61E(#QB;V]S="]P<F5P<F]C97-S M;W(O<W1R:6YG:7IE+FAP<#X-"B-I;F-L=61E($)/3U-47U!07U-44DE.1TE: M12A"3T]35%]!4D-(259%7U1%4U0I#0H-"B-I;F-L=61E(")!+FAP<"(-"@T* M:6YL:6YE('-T9#HZ;W-T<F5A;2 F(&]P97)A=&]R/#PH<W1D.CIO<W1R96%M M("8@;W,L($$@8V]N<W0@)B!A*2![#0H@(" @;W,@/#P@82YB/#P@(EQN(CL- M"B @(" C:69N9&5F($)/3U-47TY/7TE.5#8T7U0-"B @("!O<R \/"!A+F8\ M/" B7&XB.PT*(" @(&]S(#P\(&$N9SP\(")<;B([#0H@(" @(V5N9&EF#0H@ M(" @;W,@/#P@82YL/#P@(EQN(CL-"B @("!O<R \/"!A+FT\/" B7&XB.PT* M(" @(&]S(#P\(&$N;CP\(")<;B([#0H@(" @;W,@/#P@82YO/#P@(EQN(CL- M"B @("!O<R \/"!A+G \/" B7&XB.PT*(" @(&]S(#P\(&$N<3P\(")<;B([ M#0H@(" @(VEF;F1E9B!"3T]35%].3U]#5T-(05(-"B @("!O<R \/"!A+G(\ M/" B7&XB.PT*(" @("-E;F1I9@T*(" @(&]S(#P\(&$N8SP\(")<;B([#0H@ M(" @;W,@/#P@82YS/#P@(EQN(CL-"B @("!O<R \/"!A+G0\/" B7&XB.PT* M(" @(&]S(#P\(&$N=3P\(")<;B([#0H@(" @;W,@/#P@82YV/#P@(EQN(CL- M"B @("!O<R \/"!A+G<\/" B7&XB.PT*(" @(&]S(#P\(&$N>#P\(")<;B([ M#0H@(" @;W,@/#P@82YY/#P@(EQN(CL-"B @(" C:69N9&5F($)/3U-47TY/ M7U-41%]74U1224Y'#0H@(" @+R]O<R \/"!A+GH\/" B7&XB.PT*(" @("-E M;F1I9@T*(" @(')E='5R;B!O<SL-"GT-"@T*:6YL:6YE('-T9#HZ:7-T<F5A M;2 F(&]P97)A=&]R/CXH<W1D.CII<W1R96%M("8@:7,L($$@)B!A*2![#0H@ M(" @:7,@/CX@82YB.PT*(" @("-I9FYD968@0D]/4U1?3D]?24Y4-C1?5 T* M(" @(&ES(#X^(&$N9CL-"B @("!I<R ^/B!A+F<[#0H@(" @(V5N9&EF#0H@ M(" @:6YT(&D[#0H@(" @:7,@/CX@:3L-"B @("!A+FP@/2!S=&%T:6-?8V%S M=#Q!.CIH/BAI*3L-"B @("!I<R ^/B!A+FT[#0H@(" @:7,@/CX@82YN.PT* M(" @(&ES(#X^(&$N;SL-"B @("!I<R ^/B!A+G [#0H@(" @:7,@/CX@82YQ M.PT*(" @("-I9FYD968@0D]/4U1?3D]?0U=#2$%2#0H@(" @:7,@/CX@:3L- M"B @("!A+G(@/2!I.PT*(" @("-E;F1I9@T*(" @(&ES(#X^(&$N8SL-"B @ M("!I<R ^/B!A+G,[#0H@(" @:7,@/CX@82YT.PT*(" @(&ES(#X^(&$N=3L- M"B @("!I<R ^/B!A+G8[#0H@(" @:7,@/CX@82YW.PT*(" @(&ES(#X^(&$N M>#L-"B @("!I<R ^/B!A+GD[#0H@(" @(VEF;F1E9B!"3T]35%].3U]35$1? M5U-44DE.1PT*(" @("\O:7,@/CX@82YZ.PT*(" @("-E;F1I9@T*(" @(')E M='5R;B!I<SL-"GT-"@T*+R\@:G5S="!U<V4@82!W<F%P<&5R('-O('1H870@ M02!D;V5S;B=T(&=E="!T<F%C:V5D#0IC;&%S<R!T<F%C:V5D7T$@.B!P=6)L M:6,@02![#0H@(" @9G)I96YD(&)O;W-T.CIS97)I86QI>F%T:6]N.CIA8V-E M<W,[#0H@(" @=&5M<&QA=&4\8VQA<W,@07)C:&EV93X-"B @("!V;VED('-E M<FEA;&EZ92A!<F-H:79E("8@87(L(&-O;G-T('5N<VEG;F5D(&EN="!V97)S M:6]N*7L-"B @(" @(" @87(@)B!"3T]35%]315))04Q)6D%424].7T)!4T5? M3T)*14-47TY64"A!*3L-"B @("!]#0I].PT*#0HO+R!B87-E;&EN92 M(&9I M9W5R92!T:6UE('1O(&IU<W0@=W)I=&4@=&AE(&1A=&$@#0IT96UP;&%T93QU M;G-I9VYE9"!I;G0@3CX-"G9O:60@<V%V95]T97-T,2AS=&0Z.F]S=')E86T@ M)B!O<RP@8V]N<W0@02 H)B!A*5M.72E[#0H@(" @;W,N9FQU<V@H*3L-"B @ M("!B;V]S=#HZ=&EM97(@=#L-"B @("!U;G-I9VYE9"!I;G0@:2 ]($X[#0H@ M(" @=VAI;&4H:2TM(#X@,"D-"B @(" @(" @;W,@/#P@85MI72 \/" B7&XB M.PT*(" @('-T9#HZ8V]U=" \/" B=W)I=&4@=&\@9FEL92 B(#P\('0N96QA M<'-E9"@I(#P\(")M<UQN(CL-"GT-"@T*+R\@<V%V92!D871A('5S:6YG(&%N M(&%R8VAI=F4-"G1E;7!L871E/&-L87-S($%R8VAI=F4L('5N<VEG;F5D(&EN M="!./@T*=F]I9"!S879E7W1E<W0R*$%R8VAI=F4@)B!O82P@8V]N<W0@02 H M)B!A*5M.72E[#0H@(" @8F]O<W0Z.G1I;65R('0[#0H@(" @;V$@/#P@0D]/ M4U1?4T5224%,25I!5$E/3E].5E H82D[#0H@(" @<W1D.CIC;W5T(#P\(")S M879E(&%R8VAI=F4@(B \/"!T+F5L87!S960H*2 \/" B;7-<;B([#0I]#0H- M"B\O('-A=F4@9&%T82!T:')O=6=H(&$@<&]I;G1E<B!U<VEN9R!A;B!A<F-H M:79E#0IT96UP;&%T93QC;&%S<R!!<F-H:79E+"!U;G-I9VYE9"!I;G0@3CX- M"G9O:60@<V%V95]T97-T,RA!<F-H:79E("8@;V$L(&-O;G-T($$@*"8@82E; M3ETI>PT*(" @('1R86-K961?02!C;VYS=" J(&%P6TY=.PT*(" @('5N<VEG M;F5D(&EN="!I(#T@3CL-"B @("!W:&EL92AI+2T@/B P*0T*(" @(" @("!A M<%MI72 ]('-T871I8U]C87-T/'1R86-K961?02!C;VYS=" J/B@F(&%;:5TI M.PT*(" @(&)O;W-T.CIT:6UE<B!T.PT*(" @(&]A("8@0D]/4U1?4T5224%, M25I!5$E/3E].5E H87 I.PT*(" @('-T9#HZ8V]U=" \/" B<V%V92!A<F-H M:79E('1H<F]U9V@@<&]I;G1E<B B(#P\('0N96QA<'-E9"@I(#P\(")M<UQN M(CL-"GT-"@T*+R\@8F%S96QI;F4@+2!F:6=U<F4@=&EM92!T;R!J=7-T('=R M:71E('1H92!D871A( T*=&5M<&QA=&4\=6YS:6=N960@:6YT($X^#0IV;VED M(&QO861?=&5S=#$H<W1D.CII<W1R96%M("8@:7,L($$@*"8@82E;3ETI>PT* M(" @(&)O;W-T.CIT:6UE<B!T.PT*(" @('5N<VEG;F5D(&EN="!I(#T@3CL- M"B @("!W:&EL92AI+2T@/B P*0T*(" @(" @("!I<R ^/B!A6VE=.PT*(" @ M('-T9#HZ8V]U=" \/" B<F5A9"!F<F]M(&9I;&4@(B \/"!T+F5L87!S960H M*2 \/" B;7-<;B([#0I]#0H-"B\O(&QO860@9&%T82!U<VEN9R!A;B!A<F-H M:79E#0IT96UP;&%T93QC;&%S<R!!<F-H:79E+"!U;G-I9VYE9"!I;G0@3CX- M"G9O:60@;&]A9%]T97-T,BA!<F-H:79E("8@:6$L($$@*"8@82E;3ETI>PT* M(" @(&)O;W-T.CIT:6UE<B!T.PT*(" @(&EA(#X^($)/3U-47U-%4DE!3$E: M051)3TY?3E90*&$I.PT*(" @('-T9#HZ8V]U=" \/" B;&]A9"!A<F-H:79E M("(@/#P@="YE;&%P<V5D*"D@/#P@(FUS7&XB.PT*?0T*#0HO+R!L;V%D(&1A M=&$@=&AR;W5G:"!A('!O:6YT97(@=7-I;F<@86X@87)C:&EV90T*=&5M<&QA M=&4\8VQA<W,@07)C:&EV92P@=6YS:6=N960@:6YT($X^#0IV;VED(&QO861? M=&5S=#,H07)C:&EV92 F(&EA+"!!("@F(&$I6TY=*7L-"B @("!T<F%C:V5D M7T$@*B!A<%M.73L-"B @("!B;V]S=#HZ=&EM97(@=#L-"B @("!I82 ^/B!" M3T]35%]315))04Q)6D%424].7TY64"AA<"D[#0H@(" @<W1D.CIC;W5T(#P\ M(")L;V%D(&%R8VAI=F4@=&AR;W5G:"!P;VEN=&5R("(@/#P@="YE;&%P<V5D M*"D@/#P@(FUS7&XB.PT*(" @("\O(&IU<W0@:6X@8V%S92!S;VUE;VYE('=A M;G1E9"!T;R!C;VUP87)E('1H92!R97-U;'1S#0H@(" @=6YS:6=N960@:6YT M(&D@/2!..PT*(" @('=H:6QE*&DM+2 ^(# I#0H@(" @(" @(&%;:5T@/2 J M87!;:5T[#0H@(" @:6$N9&5L971E7V-R96%T961?<&]I;G1E<G,H*3L-"GT- M"@T*=&5M<&QA=&4\=6YS:6=N960@:6YT($X^#0IV;VED('1E<W1?<W1R96%M M*$$@*"8@82E;3ETI>PT*(" @('-T9#HZ8V]U=" \/" B<W1A;F1A<F0@;&EB M<F%R>5QN(CL-"B @("!C;VYS="!C:&%R("H@=&5S=&9I;&4@/2!B;V]S=#HZ M87)C:&EV93HZ=&UP;F%M*$Y53$PI.PT*(" @($)/3U-47U)%455)4D4H3E5, M3" A/2!T97-T9FEL92D[#0H@(" @=&5S=%]O<W1R96%M(&]S*'1E<W1F:6QE M+"!415-47U-44D5!35]&3$%'4RD[#0H@(" @<V%V95]T97-T,2AO<RP@82D[ M#0H@(" @;W,N8VQO<V4H*3L-"B @("!T97-T7VES=')E86T@:7,H=&5S=&9I M;&4L(%1%4U1?4U1214%-7T9,04=3*3L-"B @("!L;V%D7W1E<W0Q*&ES+"!A M*3L-"B @("!I<RYC;&]S92@I.PT*(" @('-T9#HZ<F5M;W9E*'1E<W1F:6QE M*3L-"GT-"@T*=&5M<&QA=&4\=6YS:6=N960@:6YT($X^#0IV;VED('1E<W1? M8FEN87)Y7V%R8VAI=F4H02 H)B!A*5M.72E[#0H@(" @<W1D.CIC;W5T(#P\ M(")B:6YA<GE?87)C:&EV97-<;B([#0H@(" @8V]N<W0@8VAA<B J('1E<W1F M:6QE(#T@8F]O<W0Z.F%R8VAI=F4Z.G1M<&YA;2A.54Q,*3L-"B @("!"3T]3 M5%]215%525)%*$Y53$P@(3T@=&5S=&9I;&4I.PT*(" @('-T9#HZ;V9S=')E M86T@;W,H=&5S=&9I;&4L('-T9#HZ:6]S.CIB:6YA<GDI.PT*(" @(&)O;W-T M.CIA<F-H:79E.CIB:6YA<GE?;V%R8VAI=F4@;V$H;W,I.PT*(" @('-A=F5? M=&5S=#(H;V$L(&$I.PT*(" @(&]S+F9L=7-H*"D[#0H@(" @<V%V95]T97-T M,RAO82P@82D[#0H@(" @;W,N8VQO<V4H*3L-"B @("!S=&0Z.FEF<W1R96%M M(&ES*'1E<W1F:6QE+"!S=&0Z.FEO<SHZ8FEN87)Y*3L-"B @("!B;V]S=#HZ M87)C:&EV93HZ8FEN87)Y7VEA<F-H:79E(&EA*&ES*3L-"B @("!L;V%D7W1E M<W0R*&EA+"!A*3L-"B @("!L;V%D7W1E<W0S*&EA+"!A*3L-"B @("!S=&0Z M.G)E;6]V92AT97-T9FEL92D[#0I]#0H-"G1E;7!L871E/'5N<VEG;F5D(&EN M="!./@T*=F]I9"!T97-T7W1E>'1?87)C:&EV92A!("@F(&$I6TY=*7L-"B @ M("!S=&0Z.F-O=70@/#P@(G1E>'1?87)C:&EV97-<;B([#0H@(" @8V]N<W0@ M8VAA<B J('1E<W1F:6QE(#T@8F]O<W0Z.F%R8VAI=F4Z.G1M<&YA;2A.54Q, M*3L-"B @("!"3T]35%]215%525)%*$Y53$P@(3T@=&5S=&9I;&4I.PT*(" @ M('-T9#HZ;V9S=')E86T@;W,H=&5S=&9I;&4I.PT*(" @(&)O;W-T.CIA<F-H M:79E.CIT97AT7V]A<F-H:79E(&]A*&]S*3L-"B @("!S879E7W1E<W0R*&]A M+"!A*3L-"B @("!O<RYF;'5S:"@I.PT*(" @('-A=F5?=&5S=#,H;V$L(&$I M.PT*(" @(&]S+F-L;W-E*"D[#0H@(" @<W1D.CII9G-T<F5A;2!I<RAT97-T M9FEL92D[#0H@(" @8F]O<W0Z.F%R8VAI=F4Z.G1E>'1?:6%R8VAI=F4@:6$H M:7,I.PT*(" @(&QO861?=&5S=#(H:6$L(&$I.PT*(" @(&QO861?=&5S=#,H M:6$L(&$I.PT*(" @('-T9#HZ<F5M;W9E*'1E<W1F:6QE*3L-"GT-"@T*=&5M M<&QA=&4\=6YS:6=N960@:6YT($X^#0IV;VED('1E<W1?>&UL7V%R8VAI=F4H M02 H)B!A*5M.72E[#0H@(" @<W1D.CIC;W5T(#P\(")X;6Q?87)C:&EV97-< M;B([#0H@(" @8V]N<W0@8VAA<B J('1E<W1F:6QE(#T@8F]O<W0Z.F%R8VAI M=F4Z.G1M<&YA;2A.54Q,*3L-"B @("!"3T]35%]215%525)%*$Y53$P@(3T@ M=&5S=&9I;&4I.PT*(" @('-T9#HZ;V9S=')E86T@;W,H=&5S=&9I;&4I.PT* M(" @(&)O;W-T.CIA<F-H:79E.CIX;6Q?;V%R8VAI=F4@;V$H;W,I.PT*(" @ M('-A=F5?=&5S=#(H;V$L(&$I.PT*(" @(&]S+F9L=7-H*"D[#0H@(" @<V%V M95]T97-T,RAO82P@82D[#0H@(" @;W,N8VQO<V4H*3L-"B @("!S=&0Z.FEF M<W1R96%M(&ES*'1E<W1F:6QE*3L-"B @("!B;V]S=#HZ87)C:&EV93HZ>&UL M7VEA<F-H:79E(&EA*&ES*3L-"B @("!L;V%D7W1E<W0R*&EA+"!A*3L-"B @ M("!L;V%D7W1E<W0S*&EA+"!A*3L-"B @("!S=&0Z.G)E;6]V92AT97-T9FEL M92D[#0I]#0H-"FEN=" -"G1E<W1?;6%I;B@@:6YT("\J(&%R9V,@*B\L(&-H M87(J("\J(&%R9W8@*B];72 I#0I[#0H@(" @02!A6S$P,#!=.PT*(" @('1E M<W1?<W1R96%M*&$I.PT*(" @('1E<W1?8FEN87)Y7V%R8VAI=F4H82D[#0H@ M(" @=&5S=%]T97AT7V%R8VAI=F4H82D[#0H@(" @=&5S=%]X;6Q?87)C:&EV D92AA*3L-"B @("!R971U<FX@15A)5%]354-#15-3.PT*?0T* ` end begin 666 A.hpp M(VEF;F1E9B!"3T]35%]315))04Q)6D%424].7U1%4U1?05](4% -"B-D969I M;F4@0D]/4U1?4T5224%,25I!5$E/3E]415-47T%?2%!0#0H-"B\O($U3(&-O M;7!A=&EB;&4@8V]M<&EL97)S('-U<'!O<G0@(W!R86=M82!O;F-E#0HC:68@ M9&5F:6YE9"A?35-#7U9%4BD@)B8@*%]-4T-?5D52(#X](#$P,C I#0HC('!R M86=M82!O;F-E#0HC96YD:68-"@T*+R\O+R\O+R\O,2\O+R\O+R\O+S(O+R\O M+R\O+R\S+R\O+R\O+R\O-"\O+R\O+R\O+S4O+R\O+R\O+R\V+R\O+R\O+R\O M-R\O+R\O+R\O+S@-"B\O($$N:'!P(" @('-I;7!L92!C;&%S<R!T97-T#0H- M"B\O("A#*2!#;W!Y<FEG:'0@,C P,B!2;V)E<G0@4F%M97D@+2!H='1P.B\O M=W=W+G)R<V0N8V]M("X@#0HO+R!5<V4L(&UO9&EF:6-A=&EO;B!A;F0@9&ES M=')I8G5T:6]N(&ES('-U8FIE8W0@=&\@=&AE($)O;W-T(%-O9G1W87)E#0HO M+R!,:6-E;G-E+"!697)S:6]N(#$N,"X@*%-E92!A8V-O;7!A;GEI;F<@9FEL M92!,24-%3E-%7S%?,"YT>'0@;W(@8V]P>2!A= T*+R\@:'1T<#HO+W=W=RYB M;V]S="YO<F<O3$E#14Y315\Q7S N='AT*0T*#0HO+R @4V5E(&AT=' Z+R]W M=W<N8F]O<W0N;W)G(&9O<B!U<&1A=&5S+"!D;V-U;65N=&%T:6]N+"!A;F0@ M<F5V:7-I;VX@:&ES=&]R>2X-"@T*(VEN8VQU9&4@/&-A<W-E<G0^#0HC:6YC M;'5D92 \8W-T9&QI8CX@+R\@9F]R(')A;F0H*0T*(VEN8VQU9&4@/&-M871H M/B O+R!F;W(@9F%B<R@I#0HC:6YC;'5D92 \8W-T9&1E9CX@+R\@<VEZ95]T M#0H-"B-I;F-L=61E(#QB;V]S="]C;VYF:6<N:'!P/@T*(VEF(&1E9FEN960H M0D]/4U1?3D]?4U1$0U].04U%4U!!0T4I#0IN86UE<W!A8V4@<W1D>PT*(" @ M('5S:6YG(#HZ<F%N9#L@#0H@(" @=7-I;F<@.CIF86)S.PT*(" @('5S:6YG M(#HZ<VEZ95]T.PT*?0T*(V5N9&EF#0H-"B-I;F-L=61E(#QB;V]S="]T97-T M+W1E<W1?=&]O;',N:'!P/@T*(VEN8VQU9&4@/&)O;W-T+VQI;6ET<RYH<' ^ M#0HC:6YC;'5D92 \8F]O<W0O8W-T9&EN="YH<' ^#0H-"B-I;F-L=61E(#QB M;V]S="]D971A:6PO=V]R:V%R;W5N9"YH<' ^#0HC:68@0D]/4U1?5T]22T%2 M3U5.1"A"3T]35%]$24Y+54U705)%7U-41$Q)0BP@/3T@,2D-"B-I;F-L=61E M(#QB;V]S="]A<F-H:79E+V1I;FMU;7=A<F4N:'!P/@T*(V5N9&EF#0H-"B-I M;F-L=61E(#QB;V]S="]S97)I86QI>F%T:6]N+VYV<"YH<' ^#0HC:6YC;'5D M92 \8F]O<W0O<V5R:6%L:7IA=&EO;B]S=')I;F<N:'!P/@T*(VEN8VQU9&4@ M/&)O;W-T+W-E<FEA;&EZ871I;VXO86-C97-S+FAP<#X-"@T*8VQA<W,@00T* M>PT*<')I=F%T93H-"B @("!F<FEE;F0@8VQA<W,@8F]O<W0Z.G-E<FEA;&EZ M871I;VXZ.F%C8V5S<SL-"B @(" O+R!N;W1E.B!F<F]M(&%N(&%E<W1H971I M8R!P97)S<&5C=&EV92P@22!W;W5L9"!M=6-H('!R969E<B!T;R!H879E('1H M:7,-"B @(" O+R!D969I;F5D(&]U="!O9B!L:6YE+B @56YF;W)T=6YA=&5L M>2P@=&AI<R!T<FEP<R!A(&)U9R!I;B!T:&4@5D,@-BXP#0H@(" @+R\@8V]M M<&EL97(N(%-O(&AO;&0@;W5R(&YO<V4@86YD('!U="!I="!H97(@=&\@<&5R M;6ET(')U;FYI;F<@;V8@=&5S=',N#0H@(" @=&5M<&QA=&4\8VQA<W,@07)C M:&EV93X-"B @("!V;VED('-E<FEA;&EZ92@-"B @(" @(" @07)C:&EV92 F M87(L#0H@(" @(" @(&-O;G-T('5N<VEG;F5D(&EN=" O*B!F:6QE7W9E<G-I M;VX@*B\-"B @(" I>PT*(" @(" @("!A<B F($)/3U-47U-%4DE!3$E:051) M3TY?3E90*&(I.PT*(" @(" @(" C:69N9&5F($)/3U-47TY/7TE.5#8T7U0- M"B @(" @(" @87(@)B!"3T]35%]315))04Q)6D%424].7TY64"AF*3L-"B @ M(" @(" @87(@)B!"3T]35%]315))04Q)6D%424].7TY64"AG*3L-"B @(" @ M(" @(V5N9&EF#0H@(" @(" @("-I9B!"3T]35%]73U)+05)/54Y$*%]?0D]2 M3$%.1$-?7RP@(#P](#!X-34Q("D-"B @(" @(" @(" @(&EN="!I.PT*(" @ M(" @(" @(" @:68H07)C:&EV93HZ:7-?<V%V:6YG.CIV86QU92E[#0H@(" @ M(" @(" @(" @(" @:2 ](&P[#0H@(" @(" @(" @(" @(" @87(@)B!"3T]3 M5%]315))04Q)6D%424].7TY64"AI*3L-"B @(" @(" @(" @('T-"B @(" @ M(" @(" @(&5L<V5[#0H@(" @(" @(" @(" @(" @87(@)B!"3T]35%]315)) M04Q)6D%424].7TY64"AI*3L-"B @(" @(" @(" @(" @("!L(#T@:3L-"B @ M(" @(" @(" @('T-"B @(" @(" @(V5L<V4-"B @(" @(" @(" @(&%R("8@ M0D]/4U1?4T5224%,25I!5$E/3E].5E H;"D[#0H@(" @(" @("-E;F1I9@T* M(" @(" @("!A<B F($)/3U-47U-%4DE!3$E:051)3TY?3E90*&TI.PT*(" @ M(" @("!A<B F($)/3U-47U-%4DE!3$E:051)3TY?3E90*&XI.PT*(" @(" @ M("!A<B F($)/3U-47U-%4DE!3$E:051)3TY?3E90*&\I.PT*(" @(" @("!A M<B F($)/3U-47U-%4DE!3$E:051)3TY?3E90*' I.PT*(" @(" @("!A<B F M($)/3U-47U-%4DE!3$E:051)3TY?3E90*'$I.PT*(" @(" @(" C:69N9&5F M($)/3U-47TY/7T-70TA!4@T*(" @(" @("!A<B F($)/3U-47U-%4DE!3$E: M051)3TY?3E90*'(I.PT*(" @(" @(" C96YD:68-"B @(" @(" @87(@)B!" M3T]35%]315))04Q)6D%424].7TY64"AC*3L-"B @(" @(" @87(@)B!"3T]3 M5%]315))04Q)6D%424].7TY64"AS*3L-"B @(" @(" @87(@)B!"3T]35%]3 M15))04Q)6D%424].7TY64"AT*3L-"B @(" @(" @87(@)B!"3T]35%]315)) M04Q)6D%424].7TY64"AU*3L-"B @(" @(" @87(@)B!"3T]35%]315))04Q) M6D%424].7TY64"AV*3L-"B @(" @(" @87(@)B!"3T]35%]315))04Q)6D%4 M24].7TY64"AW*3L-"B @(" @(" @87(@)B!"3T]35%]315))04Q)6D%424]. M7TY64"AX*3L-"B @(" @(" @87(@)B!"3T]35%]315))04Q)6D%424].7TY6 M4"AY*3L-"B @(" @(" @(VEF;F1E9B!"3T]35%].3U]35$1?5U-44DE.1PT* M(" @(" @("!A<B F($)/3U-47U-%4DE!3$E:051)3TY?3E90*'HI.PT*(" @ M(" @(" C96YD:68-"B @("!]#0H@(" @8F]O;"!B.PT*(" @("-I9FYD968@ M0D]/4U1?3D]?24Y4-C1?5 T*(" @(&)O;W-T.CII;G0V-%]T(&8[#0H@(" @ M8F]O<W0Z.G5I;G0V-%]T(&<[#0H@(" @(V5N9&EF#0H@(" @96YU;2!H('L- M"B @(" @(" @:2 ](# L#0H@(" @(" @(&HL#0H@(" @(" @(&L-"B @("!] M(&P[#0H@(" @<W1D.CIS:7IE7W0@;3L-"B @("!S:6=N960@;&]N9R!N.PT* M(" @('5N<VEG;F5D(&QO;F<@;SL-"B @("!S:6=N960@('-H;W)T(' [#0H@ M(" @=6YS:6=N960@<VAO<G0@<3L-"B @(" C:69N9&5F($)/3U-47TY/7T-7 M0TA!4@T*(" @('=C:&%R7W0@<CL-"B @(" C96YD:68-"B @("!C:&%R(&,[ M#0H@(" @<VEG;F5D(&-H87(@<SL-"B @("!U;G-I9VYE9"!C:&%R('0[#0H@ M(" @<VEG;F5D(&EN="!U.PT*(" @('5N<VEG;F5D(&EN="!V.PT*(" @(&9L M;V%T('<[#0H@(" @9&]U8FQE('@[#0H@(" @<W1D.CIS=')I;F<@>3L-"B @ M(" C:69N9&5F($)/3U-47TY/7U-41%]74U1224Y'#0H@(" @<W1D.CIW<W1R M:6YG('H[#0H@(" @(V5N9&EF#0IP=6)L:6,Z#0H@(" @02@I.PT*(" @(&)O M;VP@;W!E<F%T;W(]/2AC;VYS="!!("9R:',I(&-O;G-T.PT*(" @(&)O;VP@ M;W!E<F%T;W(A/2AC;VYS="!!("9R:',I(&-O;G-T.PT*(" @(&)O;VP@;W!E M<F%T;W(\*&-O;G-T($$@)G)H<RD@8V]N<W0[("\O('5S960@8GD@;&5S<PT* M(" @("\O(&AA<V@@9G5N8W1I;VX@9F]R(&-L87-S($$-"B @("!O<&5R871O M<B!S=&0Z.G-I>F5?=" H*2!C;VYS="![#0H@(" @(" @('-T9#HZ<VEZ95]T M(')E='9A;" ](# [#0H@(" @(" @("\O8V]N<W0@8VAA<B J('1P='(@/2!S M=&%T:6-?8V%S=#QC;VYS="!!("H@8V]N<W0^*'1H:7,I.PT*(" @(" @("!C M;VYS="!V;VED("H@=B ]('1H:7,[#0H@(" @(" @(&-O;G-T(&-H87(@*B!T M<'1R(#T@<W1A=&EC7V-A<W0\8V]N<W0@8VAA<B J/BAV*3L-"B @(" @(" @ M8V]N<W0@8VAA<B J('1E;F0@/2!T<'1R("L@<VEZ96]F*$$I.PT*(" @(" @ M("!W:&EL92AT<'1R(#P@=&5N9"D-"B @(" @(" @(" @(')E='9A;" K/2 J M='!T<BLK.PT*(" @(" @("!R971U<FX@<F5T=F%L.PT*(" @('T-"B @("!F M<FEE;F0@<W1D.CIO<W1R96%M("8@;W!E<F%T;W(\/"AS=&0Z.F]S=')E86T@ M)B!O<RP@02!C;VYS=" F(&$I.PT*(" @(&9R:65N9"!S=&0Z.FES=')E86T@ M)B!O<&5R871O<CX^*'-T9#HZ:7-T<F5A;2 F(&ES+"!!("8@82D[#0I].PT* M#0IT96UP;&%T93QC;&%S<R!3/@T*=F]I9"!R86YD;VUI>F4H4R F>"D-"GL- M"B @("!A<W-E<G0H," ]/2!X+G-I>F4H*2D[#0H@(" @9F]R*#L[*7L-"B @ M(" @(" @=6YS:6=N960@:6YT(&D@/2!S=&0Z.G)A;F0H*2 E(#(W.PT*(" @ M(" @("!I9B@P(#T](&DI#0H@(" @(" @(" @("!B<F5A:SL-"B @(" @(" @ M>" K/2!S=&%T:6-?8V%S=#QT>7!E;F%M92!3.CIV86QU95]T>7!E/B@G82<@ M+2 Q("L@:2D[#0H@(" @?0T*?0T*#0II;FQI;F4@03HZ02@I(#H-"B @("!B M*'1R=64I+ T*(" @("-I9FYD968@0D]/4U1?3D]?24Y4-C1?5 T*(" @(&8H M<W1D.CIR86YD*"D@*B!S=&0Z.G)A;F0H*2DL#0H@(" @9RAS=&0Z.G)A;F0H M*2 J('-T9#HZ<F%N9"@I*2P-"B @(" C96YD:68-"B @("!L*'-T871I8U]C M87-T/&5N=6T@:#XH<W1D.CIR86YD*"D@)2 S*2DL#0H@(" @;2AS=&0Z.G)A M;F0H*2DL#0H@(" @;BAS=&0Z.G)A;F0H*2DL#0H@(" @;RAS=&0Z.G)A;F0H M*2DL#0H@(" @<"AS=&0Z.G)A;F0H*2DL#0H@(" @<2AS=&0Z.G)A;F0H*2DL M#0H@(" @(VEF;F1E9B!"3T]35%].3U]#5T-(05(-"B @("!R*'-T9#HZ<F%N M9"@I*2P-"B @(" C96YD:68-"B @("!C*'-T9#HZ<F%N9"@I*2P-"B @("!S M*'-T9#HZ<F%N9"@I*2P-"B @("!T*'-T9#HZ<F%N9"@I*2P-"B @("!U*'-T M9#HZ<F%N9"@I*2P-"B @("!V*'-T9#HZ<F%N9"@I*2P-"B @("!W*"AF;&]A M="ES=&0Z.G)A;F0H*2 O('-T9#HZ<F%N9"@I*2P-"B @("!X*"AD;W5B;&4I M<W1D.CIR86YD*"D@+R!S=&0Z.G)A;F0H*2D-"GL-"B @("!R86YD;VUI>F4H M>2D[#0H@(" @(VEF;F1E9B!"3T]35%].3U]35$1?5U-44DE.1PT*(" @(')A M;F1O;6EZ92AZ*3L-"B @(" C96YD:68-"GT-"@T*:6YL:6YE(&)O;VP@03HZ M;W!E<F%T;W(]/2AC;VYS="!!("9R:',I(&-O;G-T#0I[#0H@(" @0D]/4U1? M0TA%0TLH8B ]/2!B*3L-"B @("!"3T]35%]#2$5#2RAL(#T](&PI.PT*(" @ M("-I9FYD968@0D]/4U1?3D]?24Y4-C1?5 T*(" @($)/3U-47T-(14-+*&8@ M/3T@9BD[#0H@(" @0D]/4U1?0TA%0TLH9R ]/2!G*3L-"B @(" C96YD:68- M"B @("!"3T]35%]#2$5#2RAM(#T](&TI.PT*(" @($)/3U-47T-(14-+*&X@ M/3T@;BD[#0H@(" @0D]/4U1?0TA%0TLH;R ]/2!O*3L-"B @("!"3T]35%]# M2$5#2RAP(#T](' I.PT*(" @($)/3U-47T-(14-+*'$@/3T@<2D[#0H@(" @ M(VEF;F1E9B!"3T]35%].3U]#5T-(05(-"B @("!"3T]35%]#2$5#2RAR(#T] M('(I.PT*(" @("-E;F1I9@T*(" @($)/3U-47T-(14-+*&,@/3T@8RD[#0H@ M(" @0D]/4U1?0TA%0TLH<R ]/2!S*3L-"B @("!"3T]35%]#2$5#2RAT(#T] M('0I.PT*(" @($)/3U-47T-(14-+*'4@/3T@=2D[#0H@(" @0D]/4U1?0TA% M0TLH=B ]/2!V*3L-"B @("!"3T]35%]#2$5#2RAS=&0Z.F9A8G,H=R M('<I M(#P@<W1D.CIN=6UE<FEC7VQI;6ET<SQF;&]A=#XZ.G)O=6YD7V5R<F]R*"DI M.PT*(" @($)/3U-47T-(14-+*'-T9#HZ9F%B<RAX("T@>"D@/"!S=&0Z.FYU M;65R:6-?;&EM:71S/&9L;V%T/CHZ<F]U;F1?97)R;W(H*2D[#0H@(" @0D]/ M4U1?0TA%0TLH," ]/2!Y+F-O;7!A<F4H>2DI.PT*(" @("-I9FYD968@0D]/ M4U1?3D]?4U1$7U=35%))3D<-"B @("!"3T]35%]#2$5#2R@P(#T]('HN8V]M M<&%R92AZ*2D[#0H@(" @(V5N9&EF#0H-"B @("!I9BAB("$](')H<RYB*0T* M(" @(" @("!R971U<FX@9F%L<V4[#0H@(" @:68H;" A/2!R:',N;"D-"B @ M(" @(" @<F5T=7)N(&9A;'-E.PT*(" @("-I9FYD968@0D]/4U1?3D]?24Y4 M-C1?5 T*(" @(&EF*&8@(3T@<FAS+F8I#0H@(" @(" @(')E='5R;B!F86QS M93L-"B @("!I9BAG("$](')H<RYG*0T*(" @(" @("!R971U<FX@9F%L<V4[ M#0H@(" @(V5N9&EF#0H@(" @:68H;2 A/2!R:',N;2D-"B @(" @(" @<F5T M=7)N(&9A;'-E.PT*(" @(&EF*&X@(3T@<FAS+FXI#0H@(" @(" @(')E='5R M;B!F86QS93L-"B @("!I9BAO("$](')H<RYO*0T*(" @(" @("!R971U<FX@ M9F%L<V4[#0H@(" @:68H<" A/2!R:',N<"D-"B @(" @(" @<F5T=7)N(&9A M;'-E.R -"B @("!I9BAQ("$](')H<RYQ*0T*(" @(" @("!R971U<FX@9F%L M<V4[#0H@(" @(VEF;F1E9B!"3T]35%].3U]#5T-(05(-"B @("!I9BAR("$] M(')H<RYR*0T*(" @(" @("!R971U<FX@9F%L<V4[( T*(" @("-E;F1I9@T* M(" @(&EF*&,@(3T@<FAS+F,I#0H@(" @(" @(')E='5R;B!F86QS93L-"B @ M("!I9BAS("$](')H<RYS*0T*(" @(" @("!R971U<FX@9F%L<V4[#0H@(" @ M:68H=" A/2!R:',N="D-"B @(" @(" @<F5T=7)N(&9A;'-E.PT*(" @(&EF M*'4@(3T@<FAS+G4I#0H@(" @(" @(')E='5R;B!F86QS93L@#0H@(" @:68H M=B A/2!R:',N=BD-"B @(" @(" @<F5T=7)N(&9A;'-E.R -"B @("!I9BAS M=&0Z.F9A8G,H=R M(')H<RYW*2 ^('-T9#HZ;G5M97)I8U]L:6UI=',\9FQO M870^.CIR;W5N9%]E<G)O<B@I*0T*(" @(" @("!R971U<FX@9F%L<V4[#0H@ M(" @:68H<W1D.CIF86)S*'@@+2!R:',N>"D@/B!S=&0Z.FYU;65R:6-?;&EM M:71S/&9L;V%T/CHZ<F]U;F1?97)R;W(H*2D-"B @(" @(" @<F5T=7)N(&9A M;'-E.PT*(" @(&EF*# @(3T@>2YC;VUP87)E*')H<RYY*2D-"B @(" @(" @ M<F5T=7)N(&9A;'-E.PT*(" @("-I9FYD968@0D]/4U1?3D]?4U1$7U=35%)) M3D<-"B @("!I9B@P("$]('HN8V]M<&%R92AR:',N>BDI#0H@(" @(" @(')E M='5R;B!F86QS93L-"B @(" C96YD:68@(" @(" -"B @("!R971U<FX@=')U M93L-"GT-"@T*:6YL:6YE(&)O;VP@03HZ;W!E<F%T;W(A/2AC;VYS="!!("9R M:',I(&-O;G-T#0I[#0H@(" @<F5T=7)N("$@*"IT:&ES(#T](')H<RD[#0I] M#0H-"FEN;&EN92!B;V]L($$Z.F]P97)A=&]R/"AC;VYS="!!("9R:',I(&-O M;G-T#0I[#0H@(" @:68H8B A/2!R:',N8BD-"B @(" @(" @<F5T=7)N(&(@ M/"!R:',N8CL-"B @(" C:69N9&5F($)/3U-47TY/7TE.5#8T7U0-"B @("!I M9BAF("$](')H<RYF*0T*(" @(" @("!R971U<FX@9B \(')H<RYF.PT*(" @ M(&EF*&<@(3T@<FAS+F<I#0H@(" @(" @(')E='5R;B!G(#P@<FAS+F<[#0H@ M(" @(V5N9&EF#0H@(" @:68H;" A/2!R:',N;" I#0H@(" @(" @(')E='5R M;B!L(#P@<FAS+FP[#0H@(" @:68H;2 A/2!R:',N;2 I#0H@(" @(" @(')E M='5R;B!M(#P@<FAS+FT[#0H@(" @:68H;B A/2!R:',N;B I#0H@(" @(" @ M(')E='5R;B!N(#P@<FAS+FX[#0H@(" @:68H;R A/2!R:',N;R I#0H@(" @ M(" @(')E='5R;B!O(#P@<FAS+F\[#0H@(" @:68H<" A/2!R:',N<" I#0H@ M(" @(" @(')E='5R;B!P(#P@<FAS+G [#0H@(" @:68H<2 A/2!R:',N<2 I M#0H@(" @(" @(')E='5R;B!Q(#P@<FAS+G$[#0H@(" @(VEF;F1E9B!"3T]3 M5%].3U]#5T-(05(-"B @("!I9BAR("$](')H<RYR("D-"B @(" @(" @<F5T M=7)N('(@/"!R:',N<CL-"B @(" C96YD:68-"B @("!I9BAC("$](')H<RYC M("D-"B @(" @(" @<F5T=7)N(&,@/"!R:',N8SL-"B @("!I9BAS("$](')H M<RYS("D-"B @(" @(" @<F5T=7)N(',@/"!R:',N<SL-"B @("!I9BAT("$] M(')H<RYT("D-"B @(" @(" @<F5T=7)N('0@/"!R:',N=#L-"B @("!I9BAU M("$](')H<RYU("D-"B @(" @(" @<F5T=7)N('4@/"!R:',N=3L@#0H@(" @ M:68H=B A/2!R:',N=B I#0H@(" @(" @(')E='5R;B!V(#P@<FAS+G8[#0H@ M(" @:68H=R A/2!R:',N=R I#0H@(" @(" @(')E='5R;B!W(#P@<FAS+G<[ M( T*(" @(&EF*'@@(3T@<FAS+G@@*0T*(" @(" @("!R971U<FX@>" \(')H M<RYX.PT*(" @(&EN="!I(#T@>2YC;VUP87)E*')H<RYY*3L-"B @("!I9BAI M("$](" P("D-"B @(" @(" @<F5T=7)N(&D@/" P.PT*(" @("-I9FYD968@ M0D]/4U1?3D]?4U1$7U=35%))3D<-"B @("!I;G0@:B ]('HN8V]M<&%R92AR M:',N>BD[#0H@(" @:68H:B A/2 @," I#0H@(" @(" @(')E='5R;B!J(#P@ M,#L-"B @(" C96YD:68-"B @("!R971U<FX@9F%L<V4[#0I]#0H-"B-E;F1I E9B O+R!"3T]35%]315))04Q)6D%424].7U1%4U1?05](4% -"@`` ` end

I've written a test program to compare the time required by boost serialization to the time required by using stream i/o to do a similar operation. I've only used VC 7.1 (release mode) and my focus has been to try to determine how much overhead the serialization system adds compared to the alternative of not using it. The test consists for saving/loading 1000 instances of a class which includes all primitive types (? about 20 members including strings). Times are calculated by dividing the total time by 1000 to give ms / operaton.
These preliminary results don't raise any major red flags.
Just to reiterate my experience of profiling boost::serialization loading under vtune (I cannot recommend this enough for serious performance analysis) using one of our real data files for testing (weighs in at > 100mb and thousands of individual instances of objects) that the major bottleneck was strcmp caused by the type_id compare looking up the per type information used for tracking and the such. This outweighed everything else by a wide margin. I can dig up the details if your interested and up some point I will need to look at this again and try and optimise it. This was using 1.32.0 so take the above with a grain of salt *if* this area has changed significantly. Martin -- No virus found in this outgoing message. Checked by AVG Free Edition. Version: 7.1.362 / Virus Database: 267.12.8/165 - Release Date: 9/11/2005

Wow - that is very interesting information for me. It turns out that 1.33.x does not use strmp for this purpose so maybe it will be faster. This kind of result is very much in line with my experience with profilers. It almost happens that the bottlenecks turn out to be in the last place I would have looked !!! So I am anxious to get at least the gcc profiler working for some serialization performance tests. Thanks for this very useful information. Robert Ramey Martin Slater wrote:
I've written a test program to compare the time required by boost serialization to the time required by using stream i/o to do a similar operation. I've only used VC 7.1 (release mode) and my focus has been to try to determine how much overhead the serialization system adds compared to the alternative of not using it. The test consists for saving/loading 1000 instances of a class which includes all primitive types (? about 20 members including strings). Times are calculated by dividing the total time by 1000 to give ms / operaton.
These preliminary results don't raise any major red flags.
Just to reiterate my experience of profiling boost::serialization loading under vtune (I cannot recommend this enough for serious performance analysis) using one of our real data files for testing (weighs in at > 100mb and thousands of individual instances of objects) that the major bottleneck was strcmp caused by the type_id compare looking up the per type information used for tracking and the such. This outweighed everything else by a wide margin. I can dig up the details if your interested and up some point I will need to look at this again and try and optimise it. This was using 1.32.0 so take the above with a grain of salt *if* this area has changed significantly.
Martin

Robert Ramey wrote:
Wow - that is very interesting information for me. It turns out that 1.33.x does not use strmp for this purpose so maybe it will be faster. This kind of result
This is good news, we haven't been able to upgrade to 1.33 yet, hopefully when we upgrade to vc2005 the boost upgrade can follow shortly after.
is very much in line with my experience with profilers. It almost happens that the bottlenecks turn out to be in the last place I would have looked !!!
Absolutely, profiling is the one true way to find the performance bottlenecks, anything else is an excersise in frustration. Martin -- No virus found in this outgoing message. Checked by AVG Free Edition. Version: 7.1.362 / Virus Database: 267.13.0/167 - Release Date: 11/11/2005

Martin Slater wrote:
Just to reiterate my experience of profiling boost::serialization loading under vtune (I cannot recommend this enough for serious performance analysis) using one of our real data files for testing (weighs in at > 100mb and thousands of individual instances of objects) that the major bottleneck was strcmp caused by the type_id compare looking up the per type information used for tracking and the such. This outweighed everything else by a wide margin. I can dig up the details if your interested and up some point I will need to look at this again and try and optimise it. This was using 1.32.0 so take the above with a grain of salt *if* this area has changed significantly.
A couple of observations. I believe the intel machine has hardware instructions which implement strcmp and that compilers support them. So even if strcmp is the bottleneck, I wouldn't expect it to show up on the profiler unless some sort of inlining were turned off. Or maybe the vtune profiler has special provision for these cases somewhere. I did check to verify that the strcmp in the type-id lookup has been removed. Instead we just make sure there is only one instance of a particular extended_type_info record so that we can just compare the addresses. There are still some optimizations to be implemented - but I can't predict how much they will speed up anything. Robert Ramey

On 11/12/05, Robert Ramey <ramey@rrsd.com> wrote: [snip - Martin Slater wrote]
A couple of observations.
I believe the intel machine has hardware instructions which implement strcmp and that compilers support them. So even if strcmp is the bottleneck, I wouldn't expect it to show up on the profiler unless some sort of inlining were turned off. Or maybe the vtune profiler has special provision for these cases somewhere.
If you check for extended_type_info equality using strcmp very much, I cant see why it wouldnt be a bottleneck. I dont know the details of the serialization library, but my guess is that it must find the extended_type_info which matches the type given, depending on the complexity of your find algorithm, it may have unnecessary comparitions, that would point strcmp as the bottleneck.
I did check to verify that the strcmp in the type-id lookup has been removed. Instead we just make sure there is only one instance of a particular extended_type_info record so that we can just compare the addresses. There are still some optimizations to be implemented - but I can't predict how much they will speed up anything.
IMHO, profilers are essential before any work on optimization. Probably lots of optimizations wont even be needed, while others will make the real difference in speed. I have experienced that reusing containers(as someone already posted in this mailing list as a possible solution to some bottlenecks in the serialization library) to have huge impact in performance.
Robert Ramey
best regards, -- Felipe Magno de Almeida Developer from synergy and Computer Science student from State University of Campinas(UNICAMP). Unicamp: http://www.ic.unicamp.br Synergy: http://www.synergy.com.br "There is no dark side of the moon really. Matter of fact it's all dark."

I believe the intel machine has hardware instructions which implement strcmp and that compilers support them. So even if strcmp is the bottleneck, I wouldn't expect it to show up on the profiler unless some sort of inlining were turned off. Or maybe the vtune profiler has special provision for these cases somewhere.
VTune doesn't have any special provision for this, if a function is inlined it will just show up in the function it inlined it to. Under VC by default strcmp is just a regular function call but you can enable it as a compiler intrinsic (#pragma intrinsic(strcmp) ) and the compiler may well then generate much better code (I know enabling memcpy this way can reduce memcpy(&a, &b, sizeof(int)) to a simple register mov in places).
I did check to verify that the strcmp in the type-id lookup has been removed. Instead we just make sure there is only one instance of a particular extended_type_info record so that we can just compare the addresses. There are still some optimizations
This is very good, I was looking at how to do this myself so am very happy I now don't have to;)
to be implemented - but I can't predict how much they will speed up anything.
Predication in optimisation I have found to be nigh on impossible, without a profiler or at the very least extemely heavy instrumentation within you code you will always get a shock as to where the time is spent. VC6 was a nightmare in this regard as for example it would not inline some trivial functions without being given __forceinline for that function casuing some potentially extrememly fast code to run pathetically slowly. If your interested in vtune they do an evaluation verion at https://registrationcenter.intel.com/EvalCenter/EvalForm.aspx?ProductID=319 It is simply the best profiling tool I have ever used. I'd be more than happy to help out with any profiling and optimisation I can. Martin. -- No virus found in this outgoing message. Checked by AVG Free Edition. Version: 7.1.362 / Virus Database: 267.13.0/167 - Release Date: 11/11/2005

Martin Slater wrote:
I believe the intel machine has hardware instructions which implement strcmp and that compilers support them. So even if strcmp is the bottleneck, I wouldn't expect it to show up on the profiler unless some sort of inlining were turned off. Or maybe the vtune profiler has special provision for these cases somewhere.
VTune doesn't have any special provision for this, if a function is inlined it will just show up in the function it inlined it to. Under VC by default strcmp is just a regular function call but you can enable it as a compiler intrinsic (#pragma intrinsic(strcmp) ) and the compiler may well then generate much better code (I know enabling memcpy this way can reduce memcpy(&a, &b, sizeof(int)) to a simple register mov in places).
I did check to verify that the strcmp in the type-id lookup has been removed. Instead we just make sure there is only one instance of a particular extended_type_info record so that we can just compare the addresses. There are still some optimizations
This is very good, I was looking at how to do this myself so am very happy I now don't have to;)
to be implemented - but I can't predict how much they will speed up anything.
Predication in optimisation I have found to be nigh on impossible, without a profiler or at the very least extemely heavy instrumentation within you code you will always get a shock as to where the time is spent. VC6 was a nightmare in this regard as for example it would not inline some trivial functions without being given __forceinline for that function casuing some potentially extrememly fast code to run pathetically slowly.
If your interested in vtune they do an evaluation verion at https://registrationcenter.intel.com/EvalCenter/EvalForm.aspx?ProductID=319 It is simply the best profiling tool I have ever used.
I'd be more than happy to help out with any profiling and optimisation I can.
Martin.

Martin Slater wrote:
I believe the intel machine has hardware instructions which implement strcmp and that compilers support them. So even if strcmp is the bottleneck, I wouldn't expect it to show up on the profiler unless some sort of inlining were turned off. Or maybe the vtune profiler has special provision for these cases somewhere.
VTune doesn't have any special provision for this, if a function is inlined it will just show up in the function it inlined it to. Under VC by default strcmp is just a regular function call but you can enable it as a compiler intrinsic (#pragma intrinsic(strcmp) ) and the compiler may well then generate much better code (I know enabling memcpy this way can reduce memcpy(&a, &b, sizeof(int)) to a simple register mov in places).
Hmmm - then the fact it showed up on the profiler suggests that the program wasn't compiled with full optimisation? You might want to expand upon this.
If your interested in vtune they do an evaluation verion at https://registrationcenter.intel.com/EvalCenter/EvalForm.aspx?ProductID=319 It is simply the best profiling tool I have ever used.
At one time I had the intel eval compiler installed and it was very good. My license expired and I just didn't have the incentive to actually pay for it. Too bad I would have liked to have it my test suite.
I'd be more than happy to help out with any profiling and optimisation I can.
Well, you'll get your chance pretty soon. Soon I'll be checking in my test_overhead program into the development tree. I think I can pass the compiler switches to get it to generate a profile - at least for gcc - but I'm struggling to figure out how to get bjam to invoke gprof to display the profile in the output and to make sure I can see it in the test matrix. So you may get your chance to make this work for vtune. I'm surprised that profling / bench marking isn't commonly part of the test suites of boost libraries. Robert Ramey

Hmmm - then the fact it showed up on the profiler suggests that the program wasn't compiled with full optimisation? You might want to expand upon this.
This may well be out of our control, IIRC it was coming from the crt library provided with VC, in user code you can control it via the necessary pragma but asking users to rebuild the crt library is a bit unreasonable;) Anyway if this test has been reduced to pointer / pointer comparision then all should be good.
If your interested in vtune they do an evaluation verion at https://registrationcenter.intel.com/EvalCenter/EvalForm.aspx?ProductID=319 It is simply the best profiling tool I have ever used.
At one time I had the intel eval compiler installed and it was very good. My license expired and I just didn't have the incentive to actually pay for it. Too bad I would have liked to have it my test suite.
This is just an eval for vtune, still not cheap though.
I'd be more than happy to help out with any profiling and optimisation I can.
Well, you'll get your chance pretty soon. Soon I'll be checking in my test_overhead program into the development tree. I think I can pass the compiler switches to get it to generate a profile - at least for gcc - but I'm struggling to figure out how to get bjam to invoke gprof to display the profile in the output and to make sure I can see it in the test matrix. So you may get your chance to make this work for vtune. I'm surprised that profling / bench marking isn't commonly part of the test suites of boost libraries.
Cool, i'll jump in as soon as you have it uploaded. cheers Martin -- No virus found in this outgoing message. Checked by AVG Free Edition. Version: 7.1.362 / Virus Database: 267.13.0/167 - Release Date: 11/11/2005

Some recent tests I've done that compare Ebenezer Enterprises and Boost.serialization's performance show the Boost.serialization approach to be 7 to 9 times slower than the Ebenezer Enterprises approach. I'm using Linux 2.6.12, gcc 4.0.2 (with -O3) and a Boost.serialization library from the release tree. A test that compared the times to serialize/send a list<int> took 7.4 times longer with Boost than Ebenezer. I timed the following Boost: oArch & lst; // oArch is a binary_oarchive
Ebenezer: msgs.Send(buffer, lst); // In order to compare apples to apples, // I removed a section of code at the end
// of the Send function that flushes the buffer.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This seems wrong to me, comparing library to library as it is written and as the user see's it would be much more interesting and to me makes this test pointless. If you can really just remove the flush then it probably shouldnt be there in the first place or configurable by the user on an archive by archive basis.
In a second test I added a deque of int... Boost: oArch & lst; oArch & dq; // std::deque<int> dq;
Ebenezer: msgs.Send(buffer, lst, dq);
In this case Boost took 9.1 times longer than Ebenezer Enterprises approach. If you want to run these tests with other compilers I think that would be helpful. I've been warned not to put too much emphasis on numbers from gcc.
It would be interesting to see what the results are with a vanilla version of your library as well as a feature by feature comparision to see if you really are comparing apples to apples. Martin -- No virus found in this outgoing message. Checked by AVG Free Edition. Version: 7.1.362 / Virus Database: 267.12.8/165 - Release Date: 9/11/2005
participants (4)
-
David Abrahams
-
Felipe Magno de Almeida
-
Martin Slater
-
Robert Ramey