Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #13209 > unrolled thread

Oozing poison

Started byAD <isquat@gmail.com>
First post2012-01-10 04:35 -0800
Last post2012-01-17 02:31 -0800
Articles 20 on this page of 81 — 24 participants

Back to article view | Back to comp.lang.c++


Contents

  Oozing poison AD <isquat@gmail.com> - 2012-01-10 04:35 -0800
    Re: Oozing poison Leigh Johnston <leigh@i42.co.uk> - 2012-01-10 15:19 +0000
      Re: Oozing poison AD <isquat@gmail.com> - 2012-01-11 00:43 -0800
        Re: Oozing poison "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2012-01-11 10:01 +0100
          Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-11 22:09 +1300
            Re: Oozing poison AD <isquat@gmail.com> - 2012-01-11 01:42 -0800
              Re: Oozing poison Leigh Johnston <leigh@i42.co.uk> - 2012-01-11 13:36 +0000
                Re: Oozing poison John Bokma <john@castleamber.com> - 2012-01-11 10:08 -0600
                Re: Oozing poison AD <isquat@gmail.com> - 2012-01-12 06:08 -0800
                  Re: Oozing poison Leigh Johnston <leigh@i42.co.uk> - 2012-01-12 14:13 +0000
                    Re: Oozing poison AD <isquat@gmail.com> - 2012-01-17 02:08 -0800
                      Re: Oozing poison Henrik Faber <hfaber@invalid.net> - 2012-01-17 12:50 +0100
                  Re: Oozing poison Nick Keighley <nick_keighley_nospam@hotmail.com> - 2012-01-13 02:18 -0800
                    Re: Oozing poison AD <isquat@gmail.com> - 2012-01-17 02:24 -0800
        Re: Oozing poison Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-01-11 16:50 +0000
          Re: Oozing poison AD <isquat@gmail.com> - 2012-01-12 06:04 -0800
            Re: Oozing poison Victor Bazarov <v.bazarov@comcast.invalid> - 2012-01-12 10:13 -0500
              Re: Oozing poison AD <isquat@gmail.com> - 2012-01-17 02:19 -0800
                Re: Oozing poison Victor Bazarov <v.bazarov@comcast.invalid> - 2012-01-17 08:04 -0500
                Re: Oozing poison Miles Bader <miles@gnu.org> - 2012-01-18 13:51 +0900
                  Re: Oozing poison AD <isquat@gmail.com> - 2012-01-21 04:40 -0800
                    Re: Oozing poison Quint Rankid <qbr567@gmail.com> - 2012-01-21 09:05 -0800
                      Re: Oozing poison Wil Evers <bouncer@dev.null> - 2012-01-21 18:52 +0000
                        Re: Oozing poison Quint Rankid <qbr567@gmail.com> - 2012-01-21 11:33 -0800
                          Re: Oozing poison AD <isquat@gmail.com> - 2012-01-25 02:23 -0800
                        Re: Oozing poison AD <isquat@gmail.com> - 2012-01-25 02:07 -0800
                          Re: Oozing poison Victor Bazarov <v.bazarov@comcast.invalid> - 2012-01-25 07:59 -0500
                          Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-26 07:54 +1300
                    Re: Oozing poison Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2012-01-21 22:43 -0500
                      Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-22 21:05 +1300
                        Re: Oozing poison Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2012-01-22 18:21 -0500
                      Re: Oozing poison Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-01-23 15:55 +0000
                        Re: Oozing poison gwowen <gwowen@gmail.com> - 2012-01-23 08:37 -0800
                        Re: Oozing poison Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2012-01-24 22:48 -0500
                          Re: Oozing poison Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-01-25 19:44 +0000
                          Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-26 08:56 +1300
                            Re: Oozing poison 88888 Dihedral <dihedral88888@googlemail.com> - 2012-01-25 23:04 -0800
                              Re: Oozing poison Nick Keighley <nick_keighley_nospam@hotmail.com> - 2012-01-26 03:24 -0800
                                Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-26 19:13 +0000
                                Re: Oozing poison Brian Drummond <brian@shapes.demon.co.uk> - 2012-01-27 00:12 +0000
                                  Re: Oozing poison "MikeWhy" <boat042-nospam@yahoo.com> - 2012-01-26 22:44 -0600
                                Re: Oozing poison 88888 Dihedral <dihedral88888@googlemail.com> - 2012-01-28 14:25 -0800
                    Re: Oozing poison Robert Miles <milesrf@Usenet-News.net> - 2012-02-26 22:16 -0600
                Re: Oozing poison "Gernot Frisch" <me@privacy.net> - 2012-01-24 18:21 +0100
                  Re: Oozing poison Victor Bazarov <v.bazarov@comcast.invalid> - 2012-01-24 12:41 -0500
                  Re: Oozing poison Nick Keighley <nick_keighley_nospam@hotmail.com> - 2012-01-26 03:25 -0800
                Re: Oozing poison Rui Maciel <rui.maciel@gmail.com> - 2012-01-25 19:44 +0000
                  Re: Oozing poison Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-01-26 09:44 +0000
                    Re: Oozing poison Rui Maciel <rui.maciel@gmail.com> - 2012-01-26 10:36 +0000
                      Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-26 19:18 +0000
                      Re: Oozing poison Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-01-26 20:42 +0000
                  Re: Oozing poison Juha Nieminen <nospam@thanks.invalid> - 2012-01-26 16:30 +0000
                    Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-26 19:24 +0000
                      Re: Oozing poison Cholo Lennon <chololennon@hotmail.com> - 2012-01-26 17:13 -0300
                        Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-26 20:55 +0000
                          Re: Oozing poison Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-01-26 22:08 +0000
                            Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-27 00:32 +0000
                              Re: Oozing poison Dombo <dombo@disposable.invalid> - 2012-01-28 12:59 +0100
                            Re: Oozing poison Cholo Lennon <chololennon@hotmail.com> - 2012-01-27 18:28 -0300
                              Re: Oozing poison Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-01-29 18:02 +0000
                          Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-27 20:18 +1300
                            Re: Oozing poison Miles Bader <miles@gnu.org> - 2012-01-27 18:09 +0900
                              Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-27 20:29 +0000
                                Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-28 10:06 +1300
                                  Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-27 21:26 +0000
                                    Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-28 12:22 +1300
                                      Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-28 04:18 +0000
                                        Re: Oozing poison Miles Bader <miles@gnu.org> - 2012-01-28 13:44 +0900
                                          Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-28 21:31 +0000
                                            Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-29 11:32 +1300
                                              Re: Oozing poison 88888 Dihedral <dihedral88888@googlemail.com> - 2012-01-28 14:55 -0800
                                                Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-29 11:59 +1300
                                              Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-30 17:08 +0000
                                        Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-28 18:06 +1300
                                          Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-28 22:49 +0000
                                            Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-29 12:22 +1300
                            Re: Oozing poison scott@slp53.sl.home (Scott Lurndal) - 2012-01-27 20:16 +0000
                              Re: Oozing poison Ian Collins <ian-news@hotmail.com> - 2012-01-28 10:01 +1300
                      Re: Oozing poison Juha Nieminen <nospam@thanks.invalid> - 2012-01-28 16:00 +0000
    Re: Oozing poison Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-01-10 21:42 +0000
      Re: Oozing poison AD <isquat@gmail.com> - 2012-01-17 02:31 -0800

Page 4 of 5 — ← Prev page 1 2 3 [4] 5  Next page →


#13604

FromIan Collins <ian-news@hotmail.com>
Date2012-01-27 20:18 +1300
Message-ID<9of1duF8j0U1@mid.individual.net>
In reply to#13598
On 01/27/12 09:55 AM, Scott Lurndal wrote:
> Cholo Lennon<chololennon@hotmail.com>  writes:
>> On 26/01/2012 16:24, Scott Lurndal wrote:
>>> The readability of C++ seems to get worse with each new version of the
>>> standard.   Once the<XXX>   elements (static/dynamic casts, templates) were added
>>> to the language, it became worse than perl for readability.
>>
>> Really? Do you think C++ cast operators go against readability? For me
>> is the opposite: At glance, for example, they give you more information
>> than the traditional C cast and, as a result, they are (IMHO) more readable.
>>
>
> Buenas,
>
>     I think they may provide better _maintainability_ at the expense of _readability_.
>
>     It may also be that for someone coming from a C background (starting in 1978),
> the dynamic/static cast syntax just looks alien and out of place.
>
>     Templates and exceptions on the other hand, have a distinct impact on code size
> (thus icache footprint, thus performance).

The only performance impact I have ever measured from the use of 
exceptions is improvement.  I have been testing compilers since the mid 
90s and I have only found one compiler/platform (that compiler refused 
to inline any function that could throw) where exceptions had a 
detrimental impact on performance.

In overall performance terms, templates are no worse and often a 
significant improvement over the direct C equivalent (macros) because 
they aren't necessary inlined.  They can also provide significant 
performance improvements over another C alternative, the use of void* 
and function pointers (sorting being the classic example).

Yes you can end up with multiple instances of class methods, but that is 
the price you pay for type safety.  Anyway, what proportion of a decent 
sized project would that represent?  For containers of pointers one can 
easily use inline wrappers round a container of void* to avoid bloat 
while retaining type safety.  In most code I have seen, containers of T* 
are more numerous than containers of T

Thus with contemporary tools, the twin myths of exception performance 
and template code bloat are just that: myths.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#13606

FromMiles Bader <miles@gnu.org>
Date2012-01-27 18:09 +0900
Message-ID<buozkd91pho.fsf@dhlpc061.dev.necel.com>
In reply to#13604
Ian Collins <ian-news@hotmail.com> writes:
> The only performance impact I have ever measured from the use of
> exceptions is improvement.  I have been testing compilers since the mid
> 90s and I have only found one compiler/platform (that compiler refused
> to inline any function that could throw) where exceptions had a
> detrimental impact on performance.

Yeah, generally exceptions are very cheap these days, probably cheaper
than equivalently-safe explicit-return-value-checking code.  I guess
some of the people decrying them may be remembering some of the
initial naive implementations using setjmp/longjmp (OK, I guess the
exception handling in MS's 32-bit ABI is still kinda of stinky).

> Yes you can end up with multiple instances of class methods, but that is
> the price you pay for type safety.  Anyway, what proportion of a decent
> sized project would that represent?  For containers of pointers one can
> easily use inline wrappers round a container of void* to avoid bloat
> while retaining type safety.  In most code I have seen, containers of T*
> are more numerous than containers of T

Also note that for really equivalent template expansions, one can
sometimes merge the resulting redundant functions at link-time.
In gcc, for instance, using "-ffunction-sections" at compile-time, and
"-Wl,--icf=safe" at link-time; I'm pretty sure MS's compilers have
something equivalent.

-Miles

-- 
Love is a snowmobile racing across the tundra.  Suddenly it flips over,
pinning you underneath.  At night the ice weasels come.  --Nietzsche

[toc] | [prev] | [next] | [standalone]


#13610

Fromscott@slp53.sl.home (Scott Lurndal)
Date2012-01-27 20:29 +0000
Message-ID<ZODUq.107194$487.76393@news.usenetserver.com>
In reply to#13606
Miles Bader <miles@gnu.org> writes:
>Ian Collins <ian-news@hotmail.com> writes:
>> The only performance impact I have ever measured from the use of
>> exceptions is improvement.  I have been testing compilers since the mid
>> 90s and I have only found one compiler/platform (that compiler refused
>> to inline any function that could throw) where exceptions had a
>> detrimental impact on performance.
>
>Yeah, generally exceptions are very cheap these days, probably cheaper
>than equivalently-safe explicit-return-value-checking code.  I guess
>some of the people decrying them may be remembering some of the
>initial naive implementations using setjmp/longjmp (OK, I guess the
>exception handling in MS's 32-bit ABI is still kinda of stinky).


I tried substituting a 'new uint8[xx}' call to replace a malloc with a try
catch block for bad_alloc.   I then disassembled the code.   One instruction
(to test the return value of the malloc) turned into:

   try {
        buf = new uint8[bufsize];
    7327:       4c 89 f7                mov    %r14,%rdi
    732a:       e8 f9 e0 ff ff          callq  5428 <operator new[](unsigned long)@plt>
    732f:       48 89 c5                mov    %rax,%rbp
    7332:       49 89 c5                mov    %rax,%r13
    } catch (std::exception x) {
        iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
        return false;
    }

    switch (cmd) {
    7335:       45 84 e4                test   %r12b,%r12b
    7338:       0f 84 8f 00 00 00       je     73cd <c_uniline_dlp::echo(c_iocb*)+0xdf>
    733e:       41 80 fc 08             cmp    $0x8,%r12b
    7342:       0f 85 7e 01 00 00       jne    74c6 <c_uniline_dlp::echo(c_iocb*)+0x1d8>
    7348:       e9 21 01 00 00          jmpq   746e <c_uniline_dlp::echo(c_iocb*)+0x180>
    734d:       48 89 c5                mov    %rax,%rbp
    7350:       48 83 fa 01             cmp    $0x1,%rdx
    7354:       74 08                   je     735e <c_uniline_dlp::echo(c_iocb*)+0x70>
    7356:       48 89 c7                mov    %rax,%rdi
    7359:       e8 aa de ff ff          callq  5208 <_Unwind_Resume@plt>
    uint8  *buf;
    uint8   cmd = iocb->get_op_var2();

    try {
        buf = new uint8[bufsize];
    } catch (std::exception x) {
    735e:       48 89 c7                mov    %rax,%rdi
    7361:       e8 b2 dc ff ff          callq  5018 <__cxa_get_exception_ptr@plt>
   *  library, and by certain language expressions.  You are free to derive
   *  your own %exception classes, or use a different hierarchy, or to
   *  throw non-class data (e.g., fundamental types).
   */
  class exception
  {
    7366:       48 8b 05 7b 83 20 00    mov    0x20837b(%rip),%rax        # 20f6e8 <_DYNAMIC+0x1c0>
    736d:       48 8d 40 10             lea    0x10(%rax),%rax
    7371:       48 89 04 24             mov    %rax,(%rsp)
    7375:       48 89 ef                mov    %rbp,%rdi
    7378:       e8 db e0 ff ff          callq  5458 <__cxa_begin_catch@plt>
        iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
    737d:       41 b9 00 00 00 00       mov    $0x0,%r9d
    7383:       41 b8 00 00 00 00       mov    $0x0,%r8d
    7389:       b9 00 00 00 00          mov    $0x0,%ecx
    738e:       ba 04 00 00 00          mov    $0x4,%edx
    7393:       be 00 c0 00 00          mov    $0xc000,%esi
    7398:       48 89 df                mov    %rbx,%rdi
    739b:       e8 e8 dd ff ff          callq  5188 <c_iocb::set_rd(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)@plt>
    uint8  *buf;
    uint8   cmd = iocb->get_op_var2();

    try {
        buf = new uint8[bufsize];
   } catch (std::exception x) {
    73a0:       48 89 e7                mov    %rsp,%rdi
    73a3:       e8 30 e1 ff ff          callq  54d8 <std::exception::~exception()@plt>
    73a8:       e8 7b dd ff ff          callq  5128 <__cxa_end_catch@plt>
    73ad:       0f 1f 00                nopl   (%rax)
    73b0:       e9 41 01 00 00          jmpq   74f6 <c_uniline_dlp::echo(c_iocb*)+0x208>
    73b5:       48 89 c5                mov    %rax,%rbp
    73b8:       48 89 e7                mov    %rsp,%rdi
    73bb:       e8 18 e1 ff ff          callq  54d8 <std::exception::~exception()@plt>
    73c0:       e8 63 dd ff ff          callq  5128 <__cxa_end_catch@plt>
    73c5:       48 89 ef                mov    %rbp,%rdi
    73c8:       e8 3b de ff ff          callq  5208 <_Unwind_Resume@plt>
        return false;
    }

    switch (cmd) {

versus (with malloc):

    buf = (uint8 *)malloc(bufsize);
    7136:       4c 89 ef                mov    %r13,%rdi
    7139:       e8 6a dd ff ff          callq  4ea8 <malloc@plt>
    713e:       48 89 c3                mov    %rax,%rbx
    7141:       49 89 c6                mov    %rax,%r14
    if (buf == NULL) {
    7144:       48 85 c0                test   %rax,%rax
    7147:       75 28                   jne    7171 <c_uniline_dlp::echo(c_iocb*)+0x73>
        iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
    7149:       41 b9 00 00 00 00       mov    $0x0,%r9d
    714f:       41 b8 00 00 00 00       mov    $0x0,%r8d
    7155:       b9 00 00 00 00          mov    $0x0,%ecx
    715a:       ba 04 00 00 00          mov    $0x4,%edx
    715f:       be 00 c0 00 00          mov    $0xc000,%esi
    7164:       48 89 ef                mov    %rbp,%rdi
    7167:       e8 4c de ff ff          callq  4fb8 <c_iocb::set_rd(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)@plt>
        return false;
    716c:       e9 40 01 00 00          jmpq   72b1 <c_uniline_dlp::echo(c_iocb*)+0x1b3>
    }

    switch (cmd) {

scott

[toc] | [prev] | [next] | [standalone]


#13612

FromIan Collins <ian-news@hotmail.com>
Date2012-01-28 10:06 +1300
Message-ID<9oghusF8j0U4@mid.individual.net>
In reply to#13610
On 01/28/12 09:29 AM, Scott Lurndal wrote:
> Miles Bader<miles@gnu.org>  writes:
>> Ian Collins<ian-news@hotmail.com>  writes:
>>> The only performance impact I have ever measured from the use of
>>> exceptions is improvement.  I have been testing compilers since the mid
>>> 90s and I have only found one compiler/platform (that compiler refused
>>> to inline any function that could throw) where exceptions had a
>>> detrimental impact on performance.
>>
>> Yeah, generally exceptions are very cheap these days, probably cheaper
>> than equivalently-safe explicit-return-value-checking code.  I guess
>> some of the people decrying them may be remembering some of the
>> initial naive implementations using setjmp/longjmp (OK, I guess the
>> exception handling in MS's 32-bit ABI is still kinda of stinky).
>
>
> I tried substituting a 'new uint8[xx}' call to replace a malloc with a try
> catch block for bad_alloc.   I then disassembled the code.   One instruction
> (to test the return value of the malloc) turned into:
>

How comes one version has multiple calls to new and the other one call 
to malloc?

What was the original source?

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#13613

Fromscott@slp53.sl.home (Scott Lurndal)
Date2012-01-27 21:26 +0000
Message-ID<3EEUq.107196$487.32649@news.usenetserver.com>
In reply to#13612
Ian Collins <ian-news@hotmail.com> writes:
>On 01/28/12 09:29 AM, Scott Lurndal wrote:
>> Miles Bader<miles@gnu.org>  writes:
>>> Ian Collins<ian-news@hotmail.com>  writes:
>>>> The only performance impact I have ever measured from the use of
>>>> exceptions is improvement.  I have been testing compilers since the mid
>>>> 90s and I have only found one compiler/platform (that compiler refused
>>>> to inline any function that could throw) where exceptions had a
>>>> detrimental impact on performance.
>>>
>>> Yeah, generally exceptions are very cheap these days, probably cheaper
>>> than equivalently-safe explicit-return-value-checking code.  I guess
>>> some of the people decrying them may be remembering some of the
>>> initial naive implementations using setjmp/longjmp (OK, I guess the
>>> exception handling in MS's 32-bit ABI is still kinda of stinky).
>>
>>
>> I tried substituting a 'new uint8[xx}' call to replace a malloc with a try
>> catch block for bad_alloc.   I then disassembled the code.   One instruction
>> (to test the return value of the malloc) turned into:
>>
>
>How comes one version has multiple calls to new and the other one call 
>to malloc?
>
>What was the original source?
>

    uint8   cmd = iocb->get_op_var2();

    buf = (uint8 *)malloc(bufsize);
    if (buf == NULL) {
        iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
        return false;
    }

    switch (cmd) {

vs.

    uint8   cmd = iocb->get_op_var2();

    try {
        buf = new uint8[bufsize];
    } catch (std::exception e) {
        iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
        return false;
    }

    switch (cmd) {


There is only one call to operator new (at 732a), the source code
is intermixed with the assembler by the 'objdump' utility and it replicated the source
line in multiple places.

scott

[toc] | [prev] | [next] | [standalone]


#13617

FromIan Collins <ian-news@hotmail.com>
Date2012-01-28 12:22 +1300
Message-ID<9ogpsvF8j0U6@mid.individual.net>
In reply to#13613
On 01/28/12 10:26 AM, Scott Lurndal wrote:
> Ian Collins<ian-news@hotmail.com>  writes:
>> On 01/28/12 09:29 AM, Scott Lurndal wrote:
>>>
>>>
>>> I tried substituting a 'new uint8[xx}' call to replace a malloc with a try
>>> catch block for bad_alloc.   I then disassembled the code.   One instruction
>>> (to test the return value of the malloc) turned into:
>>>
>>
>> How comes one version has multiple calls to new and the other one call
>> to malloc?
>>
>> What was the original source?
>>
>
>      uint8   cmd = iocb->get_op_var2();
>
>      buf = (uint8 *)malloc(bufsize);
>      if (buf == NULL) {
>          iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
>          return false;
>      }
>
>      switch (cmd) {
>
> vs.
>
>      uint8   cmd = iocb->get_op_var2();
>
>      try {
>          buf = new uint8[bufsize];
>      } catch (std::exception e) {

never catch exceptions by value, always catch by const reference to 
avoid slicing.

>          iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
>          return false;
>      }
>
>      switch (cmd) {
>
> There is only one call to operator new (at 732a), the source code
> is intermixed with the assembler by the 'objdump' utility and it replicated the source
> line in multiple places.

This is fairly atypical use of exceptions, mixing exceptions and return 
codes. It is more common to catch the exception at a higher call.  This 
simplifies the source and machine code (fewer conditional branches).

The catch is also the reason for all the extra code, constructing and 
destructing a temporary std::exception object.  The actual exception 
handling part of the code is this bit:

    } catch (std::exception x) {
     73a0:       48 89 e7                mov    %rsp,%rdi
     73a3:       e8 30 e1 ff ff          callq  54d8 
<std::exception::~exception()@plt>
     73a8:       e8 7b dd ff ff          callq  5128 <__cxa_end_catch@plt>
     73ad:       0f 1f 00                nopl   (%rax)
     73b0:       e9 41 01 00 00          jmpq   74f6 
<c_uniline_dlp::echo(c_iocb*)+0x208>
     73b5:       48 89 c5                mov    %rax,%rbp
     73b8:       48 89 e7                mov    %rsp,%rdi
     73bb:       e8 18 e1 ff ff          callq  54d8 
<std::exception::~exception()@plt>
     73c0:       e8 63 dd ff ff          callq  5128 <__cxa_end_catch@plt>
     73c5:       48 89 ef                mov    %rbp,%rdi
     73c8:       e8 3b de ff ff          callq  5208 <_Unwind_Resume@plt>
         return false;
     }

hardly bloat!  Now if the exception is caught higher up the call chain 
(with f() being a void function), there would be less, rather than more 
code.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#13619

Fromscott@slp53.sl.home (Scott Lurndal)
Date2012-01-28 04:18 +0000
Message-ID<qGKUq.152389$624.85025@news.usenetserver.com>
In reply to#13617
Ian Collins <ian-news@hotmail.com> writes:
>On 01/28/12 10:26 AM, Scott Lurndal wrote:
>> Ian Collins<ian-news@hotmail.com>  writes:
>>> On 01/28/12 09:29 AM, Scott Lurndal wrote:
>>>>
>>>>
>>>> I tried substituting a 'new uint8[xx}' call to replace a malloc with a try
>>>> catch block for bad_alloc.   I then disassembled the code.   One instruction
>>>> (to test the return value of the malloc) turned into:
>>>>
>>>
>>> How comes one version has multiple calls to new and the other one call
>>> to malloc?
>>>
>>> What was the original source?
>>>
>>
>>      uint8   cmd = iocb->get_op_var2();
>>
>>      buf = (uint8 *)malloc(bufsize);
>>      if (buf == NULL) {
>>          iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
>>          return false;
>>      }
>>
>>      switch (cmd) {
>>
>> vs.
>>
>>      uint8   cmd = iocb->get_op_var2();
>>
>>      try {
>>          buf = new uint8[bufsize];
>>      } catch (std::exception e) {
>
>never catch exceptions by value, always catch by const reference to 
>avoid slicing.

Good to know, I guess.   Since I intend to keep the malloc and forgo
the try/catch clause, the point is however moot.

>
>>          iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
>>          return false;
>>      }
>>
>>      switch (cmd) {
>>
>> There is only one call to operator new (at 732a), the source code
>> is intermixed with the assembler by the 'objdump' utility and it replicated the source
>> line in multiple places.
>
>This is fairly atypical use of exceptions, mixing exceptions and return 
>codes. It is more common to catch the exception at a higher call.  This 
>simplifies the source and machine code (fewer conditional branches).

However, in this case (modeling a physical device), the best determination
of how to present the failure  can be made as close to the cause of the
exception as possible.   I would think that for most applications that
can actually recover from an error (as opposed to just catching std::exception
at the top level, printing a message, and exiting), keeping the recovery action
as close to the code that actually failed makes recovery much simpler.

 
>
>The catch is also the reason for all the extra code, constructing and 
>destructing a temporary std::exception object.  The actual exception 
>handling part of the code is this bit:

Yet creating and destroying a temporary std::exception object also counts in
terms of both extra cycles and code footprint.   Both of which impact
performance (generally negatively).

And indeed, some simple performance testing of code running under the simulation
(a 15,000 line BPL compile), shows that when I try exceptions in one of the common
allocation paths, the performance of the BPL compile drops from 17,177 records compiled
per minute to 16,585 records compiled per minute - an almost 4% performance degredation;
this is actually worse than I expected for a single conversion from malloc/init to
new/constructor with try/catch - I'll need to dig into this further.


>
>    } catch (std::exception x) {
>     73a0:       48 89 e7                mov    %rsp,%rdi
>     73a3:       e8 30 e1 ff ff          callq  54d8 
><std::exception::~exception()@plt>
>     73a8:       e8 7b dd ff ff          callq  5128 <__cxa_end_catch@plt>
>     73ad:       0f 1f 00                nopl   (%rax)
>     73b0:       e9 41 01 00 00          jmpq   74f6 
><c_uniline_dlp::echo(c_iocb*)+0x208>
>     73b5:       48 89 c5                mov    %rax,%rbp
>     73b8:       48 89 e7                mov    %rsp,%rdi
>     73bb:       e8 18 e1 ff ff          callq  54d8 
><std::exception::~exception()@plt>
>     73c0:       e8 63 dd ff ff          callq  5128 <__cxa_end_catch@plt>
>     73c5:       48 89 ef                mov    %rbp,%rdi
>     73c8:       e8 3b de ff ff          callq  5208 <_Unwind_Resume@plt>
>         return false;
>     }
>
>hardly bloat!  Now if the exception is caught higher up the call chain 
>(with f() being a void function), there would be less, rather than more 
>code.

40 bytes. more than half a cache line each occurance (and you really should
count the exception object constructor/destructors too).   In some cases, it really matters.

And placing the catch higher in the call chain is not possible (at least not without
adding a large number of conditionals and carrying a great deal of state in
some derived exception class to the catch).

scott

[toc] | [prev] | [next] | [standalone]


#13620

FromMiles Bader <miles@gnu.org>
Date2012-01-28 13:44 +0900
Message-ID<87d3a44es0.fsf@catnip.gol.com>
In reply to#13619
scott@slp53.sl.home (Scott Lurndal) writes:
>>The catch is also the reason for all the extra code, constructing and 
>>destructing a temporary std::exception object.  The actual exception 
>>handling part of the code is this bit:
>
> Yet creating and destroying a temporary std::exception object also counts in
> terms of both extra cycles and code footprint.   Both of which impact
> performance (generally negatively).

Er, exceptions are intended to be _exceptional_.

If some exception occurs so often that it has a measurable performance
impact, it probably shouldn't be an exception.

If you look at the code generated for the two styles, one of the big
differences with the exception-using code is that the _normal_ case
(where no exception is raised) is smaller and faster, since it can
basically proceed without considering the exceptional case.  The
exception-handling code is out-of-line, to avoid a negative icache
impact.

[Also note that much "handling" of exceptions is not actually "reacting"
to specific exceptions, but simply cleaning up and propagating an error;
in C++, this typically happens via RAII (i.e. "unwind-protect" in lisp),
or "catch(...)", and those have very low space overhead, as they do not
need to do any kind of allocation/copying/matching; mostly they simply
execute the user code to do whatever is needed.]

-Miles

-- 
Carefully crafted initial estimates reward you not only with
reduced computational effort, but also with understanding and
increased self-esteem.         -- Numerical methods in C,
  Chapter 9. "Root Finding and Nonlinear Sets of Equations"

[toc] | [prev] | [next] | [standalone]


#13631

Fromscott@slp53.sl.home (Scott Lurndal)
Date2012-01-28 21:31 +0000
Message-ID<ROZUq.97141$ka3.2190@news.usenetserver.com>
In reply to#13620
Miles Bader <miles@gnu.org> writes:
>scott@slp53.sl.home (Scott Lurndal) writes:
>>>The catch is also the reason for all the extra code, constructing and 
>>>destructing a temporary std::exception object.  The actual exception 
>>>handling part of the code is this bit:
>>
>> Yet creating and destroying a temporary std::exception object also counts in
>> terms of both extra cycles and code footprint.   Both of which impact
>> performance (generally negatively).
>
>Er, exceptions are intended to be _exceptional_.
>
>If some exception occurs so often that it has a measurable performance
>impact, it probably shouldn't be an exception.

The exception never occurs (i.e., I never run out of memory).   It's the
added code to handle the exception and it's effect on a (very) hot codepath
that causes the 4% hit in performance.   That is the only change in the
codebase, and I ran the benchmark three times with each flavor (try/catch/new
vs. malloc).  I have to admit that I was surprised by the difference and I'm
going to take a look at the actual codepaths and do some profiling to see why
adding a try/catch clause has such a large effect, when the exception is never
taken.

scott

[toc] | [prev] | [next] | [standalone]


#13636

FromIan Collins <ian-news@hotmail.com>
Date2012-01-29 11:32 +1300
Message-ID<9ojbcpF8j0U13@mid.individual.net>
In reply to#13631
On 01/29/12 10:31 AM, Scott Lurndal wrote:
> Miles Bader<miles@gnu.org>  writes:
>> scott@slp53.sl.home (Scott Lurndal) writes:
>>>> The catch is also the reason for all the extra code, constructing and
>>>> destructing a temporary std::exception object.  The actual exception
>>>> handling part of the code is this bit:
>>>
>>> Yet creating and destroying a temporary std::exception object also counts in
>>> terms of both extra cycles and code footprint.   Both of which impact
>>> performance (generally negatively).
>>
>> Er, exceptions are intended to be _exceptional_.
>>
>> If some exception occurs so often that it has a measurable performance
>> impact, it probably shouldn't be an exception.
>
> The exception never occurs (i.e., I never run out of memory).   It's the
> added code to handle the exception and it's effect on a (very) hot codepath
> that causes the 4% hit in performance.   That is the only change in the
> codebase, and I ran the benchmark three times with each flavor (try/catch/new
> vs. malloc).  I have to admit that I was surprised by the difference and I'm
> going to take a look at the actual codepaths and do some profiling to see why
> adding a try/catch clause has such a large effect, when the exception is never
> taken.

How about new (without the exceptions) compared to malloc?  new is doing 
more work than malloc, one reason I suggested a specialised allocator.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#13638

From88888 Dihedral <dihedral88888@googlemail.com>
Date2012-01-28 14:55 -0800
Message-ID<15745250.325.1327791325896.JavaMail.geo-discussion-forums@prhs5>
In reply to#13636
在 2012年1月29日星期日UTC+8上午6时32分57秒,Ian Collins写道:
> On 01/29/12 10:31 AM, Scott Lurndal wrote:
> > Miles Bader<mi...@gnu.org>  writes:
> >> scott@slp53.sl.home (Scott Lurndal) writes:
> >>>> The catch is also the reason for all the extra code, constructing and
> >>>> destructing a temporary std::exception object.  The actual exception
> >>>> handling part of the code is this bit:
> >>>
> >>> Yet creating and destroying a temporary std::exception object also counts in
> >>> terms of both extra cycles and code footprint.   Both of which impact
> >>> performance (generally negatively).
> >>
> >> Er, exceptions are intended to be _exceptional_.
> >>
> >> If some exception occurs so often that it has a measurable performance
> >> impact, it probably shouldn't be an exception.
> >
> > The exception never occurs (i.e., I never run out of memory).   It's the
> > added code to handle the exception and it's effect on a (very) hot codepath
> > that causes the 4% hit in performance.   That is the only change in the
> > codebase, and I ran the benchmark three times with each flavor (try/catch/new
> > vs. malloc).  I have to admit that I was surprised by the difference and I'm
> > going to take a look at the actual codepaths and do some profiling to see why
> > adding a try/catch clause has such a large effect, when the exception is never
> > taken.
> 
> How about new (without the exceptions) compared to malloc?  new is doing 
> more work than malloc, one reason I suggested a specialised allocator.
> 
> -- 
> Ian Collins

Well, an object with some methods to generate new objects not to be garbage collected very soon following  the o stack push-pop mechnism  of auto varibles are somewaht evil in C++ if the programmer does not think carefully and write codes to chain these methods in class B arbitrarily then there might be a definitely expoenti ally growth rate of the heap used by a lousy fat programming hog  in some programs.

[toc] | [prev] | [next] | [standalone]


#13639

FromIan Collins <ian-news@hotmail.com>
Date2012-01-29 11:59 +1300
Message-ID<9ojcuqF8j0U15@mid.individual.net>
In reply to#13638
On 01/29/12 11:55 AM, 88888 Dihedral wrote:
> 在 2012年1月29日星期日UTC+8上午6时32分57秒,Ian Collins写道:
>> On 01/29/12 10:31 AM, Scott Lurndal wrote:
>>> Miles Bader<mi...@gnu.org>   writes:
>>>> scott@slp53.sl.home (Scott Lurndal) writes:
>>>>>> The catch is also the reason for all the extra code, constructing and
>>>>>> destructing a temporary std::exception object.  The actual exception
>>>>>> handling part of the code is this bit:
>>>>>
>>>>> Yet creating and destroying a temporary std::exception object also counts in
>>>>> terms of both extra cycles and code footprint.   Both of which impact
>>>>> performance (generally negatively).
>>>>
>>>> Er, exceptions are intended to be _exceptional_.
>>>>
>>>> If some exception occurs so often that it has a measurable performance
>>>> impact, it probably shouldn't be an exception.
>>>
>>> The exception never occurs (i.e., I never run out of memory).   It's the
>>> added code to handle the exception and it's effect on a (very) hot codepath
>>> that causes the 4% hit in performance.   That is the only change in the
>>> codebase, and I ran the benchmark three times with each flavor (try/catch/new
>>> vs. malloc).  I have to admit that I was surprised by the difference and I'm
>>> going to take a look at the actual codepaths and do some profiling to see why
>>> adding a try/catch clause has such a large effect, when the exception is never
>>> taken.
>>
>> How about new (without the exceptions) compared to malloc?  new is doing
>> more work than malloc, one reason I suggested a specialised allocator.
>
> Well, an object with some methods to generate new objects not to be garbage collected very soon following  the o stack push-pop mechnism  of auto varibles are somewaht evil in C++ if the programmer does not think carefully and write codes to chain these methods in class B arbitrarily then there might be a definitely expoenti ally growth rate of the heap used by a lousy fat programming hog  in some programs.

Do what?

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#13665

Fromscott@slp53.sl.home (Scott Lurndal)
Date2012-01-30 17:08 +0000
Message-ID<g8AVq.191682$IC2.182329@news.usenetserver.com>
In reply to#13636
Ian Collins <ian-news@hotmail.com> writes:
>On 01/29/12 10:31 AM, Scott Lurndal wrote:
>> Miles Bader<miles@gnu.org>  writes:
>>> scott@slp53.sl.home (Scott Lurndal) writes:
>>>>> The catch is also the reason for all the extra code, constructing and
>>>>> destructing a temporary std::exception object.  The actual exception
>>>>> handling part of the code is this bit:
>>>>
>>>> Yet creating and destroying a temporary std::exception object also counts in
>>>> terms of both extra cycles and code footprint.   Both of which impact
>>>> performance (generally negatively).
>>>
>>> Er, exceptions are intended to be _exceptional_.
>>>
>>> If some exception occurs so often that it has a measurable performance
>>> impact, it probably shouldn't be an exception.
>>
>> The exception never occurs (i.e., I never run out of memory).   It's the
>> added code to handle the exception and it's effect on a (very) hot codepath
>> that causes the 4% hit in performance.   That is the only change in the
>> codebase, and I ran the benchmark three times with each flavor (try/catch/new
>> vs. malloc).  I have to admit that I was surprised by the difference and I'm
>> going to take a look at the actual codepaths and do some profiling to see why
>> adding a try/catch clause has such a large effect, when the exception is never
>> taken.
>
>How about new (without the exceptions) compared to malloc?  new is doing 
>more work than malloc, one reason I suggested a specialised allocator.
>

I've tried using new (sans catch) and malloc both.   The difference there is
pretty much in the noise.   I've been planning on trying the gcc option -fcheck-new
with the 'new' to handle the case where new returns null (to prevent the constructor
from running) and compare that with malloc;  this will add a test and
branch to the hot path, I suspect.   If I use new (nothrow), will that still call
the constructor (and SIGSEGV) if the new returns NULL?

I ported a pool allocator over the weekend that can be used with an overloaded
new operator

   void *operator new(size_t, c_pool *p) { return p->alloc(); }

The pool class uses ::mmap(MAP_ANONYMOUS) to get pages which are then subdivided
into appropriately sized chunks (16-byte aligned for efficiency on 64-bit
architectures).

 c_pool   *pool;
 pool = new c_pool("Class Objects", sizeof(c_class), 100);  // At init time

 ...

 object =  new (pool) c_class();    // at run time

This is highly efficient in the cases where you know a priori that you'll
never run out of pool elements (sans a coding error, of course).

A downside is you can't use delete but rather must pool->free(object).

scott

[toc] | [prev] | [next] | [standalone]


#13621

FromIan Collins <ian-news@hotmail.com>
Date2012-01-28 18:06 +1300
Message-ID<9ohe2qF8j0U9@mid.individual.net>
In reply to#13619
On 01/28/12 05:18 PM, Scott Lurndal wrote:
> Ian Collins<ian-news@hotmail.com>  writes:
>> On 01/28/12 10:26 AM, Scott Lurndal wrote:
>>> Ian Collins<ian-news@hotmail.com>   writes:
>>>> On 01/28/12 09:29 AM, Scott Lurndal wrote:
>>>>>
>>>>>
>>>>> I tried substituting a 'new uint8[xx}' call to replace a malloc with a try
>>>>> catch block for bad_alloc.   I then disassembled the code.   One instruction
>>>>> (to test the return value of the malloc) turned into:
>>>>>
>>>>
>>>> How comes one version has multiple calls to new and the other one call
>>>> to malloc?
>>>>
>>>> What was the original source?
>>>>
>>>
>>>       uint8   cmd = iocb->get_op_var2();
>>>
>>>       buf = (uint8 *)malloc(bufsize);
>>>       if (buf == NULL) {
>>>           iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
>>>           return false;
>>>       }
>>>
>>>       switch (cmd) {
>>>
>>> vs.
>>>
>>>       uint8   cmd = iocb->get_op_var2();
>>>
>>>       try {
>>>           buf = new uint8[bufsize];
>>>       } catch (std::exception e) {
>>
>> never catch exceptions by value, always catch by const reference to
>> avoid slicing.
>
> Good to know, I guess.   Since I intend to keep the malloc and forgo
> the try/catch clause, the point is however moot.

But it is a typical novice error that leads to false assumptions 
regarding exception performance.

>>
>>>           iocb->set_rd(IOT_WITH_EXCEPTIONS, RD1_OCS_MPU_PARITY);
>>>           return false;
>>>       }
>>>
>>>       switch (cmd) {
>>>
>>> There is only one call to operator new (at 732a), the source code
>>> is intermixed with the assembler by the 'objdump' utility and it replicated the source
>>> line in multiple places.
>>
>> This is fairly atypical use of exceptions, mixing exceptions and return
>> codes. It is more common to catch the exception at a higher call.  This
>> simplifies the source and machine code (fewer conditional branches).
>
> However, in this case (modeling a physical device), the best determination
> of how to present the failure  can be made as close to the cause of the
> exception as possible.   I would think that for most applications that
> can actually recover from an error (as opposed to just catching std::exception
> at the top level, printing a message, and exiting), keeping the recovery action
> as close to the code that actually failed makes recovery much simpler.

It may well be, but the catch and the throw my still be several calls 
away.  Using nested small functions is much cleaner with exceptions than 
with return codes.  In your example you return the state in the object 
passed.  An exception based design may well pass the state in an 
application specific exception.

>> The catch is also the reason for all the extra code, constructing and
>> destructing a temporary std::exception object.  The actual exception
>> handling part of the code is this bit:
>
> Yet creating and destroying a temporary std::exception object also counts in
> terms of both extra cycles and code footprint.   Both of which impact
> performance (generally negatively).

Only if the exceptional condition occurs.  The normal path of execution 
will not be impacted (and will be cleaner and faster than the error 
checking case).

> And indeed, some simple performance testing of code running under the simulation
> (a 15,000 line BPL compile), shows that when I try exceptions in one of the common
> allocation paths, the performance of the BPL compile drops from 17,177 records compiled
> per minute to 16,585 records compiled per minute - an almost 4% performance degredation;
> this is actually worse than I expected for a single conversion from malloc/init to
> new/constructor with try/catch - I'll need to dig into this further.

If you are mixing exceptions and return codes, you aren't really making 
a fair comparison.  It is very likely you could improve the performance 
in other ways, such as a specialised allocator.  If your application was 
designed to use exceptions throughout, I bet you would see a performance 
improvement.

>>
>>     } catch (std::exception x) {
>>      73a0:       48 89 e7                mov    %rsp,%rdi
>>      73a3:       e8 30 e1 ff ff          callq  54d8
>> <std::exception::~exception()@plt>
>>      73a8:       e8 7b dd ff ff          callq  5128<__cxa_end_catch@plt>
>>      73ad:       0f 1f 00                nopl   (%rax)
>>      73b0:       e9 41 01 00 00          jmpq   74f6
>> <c_uniline_dlp::echo(c_iocb*)+0x208>
>>      73b5:       48 89 c5                mov    %rax,%rbp
>>      73b8:       48 89 e7                mov    %rsp,%rdi
>>      73bb:       e8 18 e1 ff ff          callq  54d8
>> <std::exception::~exception()@plt>
>>      73c0:       e8 63 dd ff ff          callq  5128<__cxa_end_catch@plt>
>>      73c5:       48 89 ef                mov    %rbp,%rdi
>>      73c8:       e8 3b de ff ff          callq  5208<_Unwind_Resume@plt>
>>          return false;
>>      }
>>
>> hardly bloat!  Now if the exception is caught higher up the call chain
>> (with f() being a void function), there would be less, rather than more
>> code.
>
> 40 bytes. more than half a cache line each occurance (and you really should
> count the exception object constructor/destructors too).   In some cases, it really matters.

No I shouldn't.

It only occurred in your code because you caught by valve.  No exception 
object is created unless one is thrown.  I also quoted more code than I 
should (because of the catch by value).  Change your code to catch by 
const reference and you will see.  For example, a bare bones example 
with gcc:

bool f( X* iocb ){
   try {
     uint8_t* buf = new uint8_t[bufsize];
     return true;
   }
   catch (const std::exception& e) {
     return false;
   }
}

compiles to (removing some labels for brevity):

	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	movl	$42, (%esp)
	call	_Znaj
	movl	$1, %eax
	leave
	ret
.L6:
	subl	$1, %edx
	je	.L4
	movl	%eax, (%esp)
	call	_Unwind_Resume
.L4:
	movl	%eax, (%esp)
	call	__cxa_begin_catch
	call	__cxa_end_catch
	xorl	%eax, %eax
	leave
	ret

> And placing the catch higher in the call chain is not possible (at least not without
> adding a large number of conditionals and carrying a great deal of state in
> some derived exception class to the catch).

The state has to be carried somewhere...  If it is only required in the 
case of an error, the exception is the logical place for it.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#13637

Fromscott@slp53.sl.home (Scott Lurndal)
Date2012-01-28 22:49 +0000
Message-ID<0Y_Uq.11149$Jp3.8515@news.usenetserver.com>
In reply to#13621
Ian Collins <ian-news@hotmail.com> writes:
>On 01/28/12 05:18 PM, Scott Lurndal wrote:

>> However, in this case (modeling a physical device), the best determination
>> of how to present the failure  can be made as close to the cause of the
>> exception as possible.   I would think that for most applications that
>> can actually recover from an error (as opposed to just catching std::exception
>> at the top level, printing a message, and exiting), keeping the recovery action
>> as close to the code that actually failed makes recovery much simpler.
>
>It may well be, but the catch and the throw my still be several calls 
>away.  Using nested small functions is much cleaner with exceptions than 
>with return codes.  In your example you return the state in the object 
>passed.  An exception based design may well pass the state in an 
>application specific exception.

Which  will have additional  overhead to allocate, construct,
destroy and deallocate the application class derived from std::exception, nicht wahr?

I think you would find that "small nested functions" is exactly what is
used, and in this case, the object passed doesn't necessary _return_ the state
passed so much as provide a channel for returning the state to the final
receipient.

Now in the core processor simulation code sigsetjmp/siglongjmp are used to reset
the simulated processor to the start of the instruction processing loop when
an exception occurs executing an instruction (an address error, invalid instruction,
etc).   These could possibly be converted to exceptions, but I'm quite sure that
the performance would be worse and the RAS characteristics of the application
wouldn't change appreciably.

I remember reading Tom Cargill's article on exceptions back when they were
introduced to the language - I think many of his points still apply - exceptions
are not a universal panacea and careful analysis of all codepaths need be done
to prevent memory leaks or access to deallocated data when exceptions are being
thrown.    The same caveats, of course, apply to setjmp/longjmp as well, but I
don't need to allocate an exception object (just set one of 10 bits in a member
field of the current 'this' when the longjmp is issued; the jmp_buf also a member
of the current object).

>
>>> The catch is also the reason for all the extra code, constructing and
>>> destructing a temporary std::exception object.  The actual exception
>>> handling part of the code is this bit:
>>
>> Yet creating and destroying a temporary std::exception object also counts in
>> terms of both extra cycles and code footprint.   Both of which impact
>> performance (generally negatively).
>
>Only if the exceptional condition occurs.  The normal path of execution 
>will not be impacted (and will be cleaner and faster than the error 
>checking case).

I haven't seen this in practice, but then my sole exposure to C++ code
has been in the Operating Systems/Microkernel/Hypervisor area none of which
used exceptions (most of which predated exceptions :-), aside from one
application at a major internet certification authority, which also predated
exceptions.

>
>> And indeed, some simple performance testing of code running under the simulation
>> (a 15,000 line BPL compile), shows that when I try exceptions in one of the common
>> allocation paths, the performance of the BPL compile drops from 17,177 records compiled
>> per minute to 16,585 records compiled per minute - an almost 4% performance degredation;
>> this is actually worse than I expected for a single conversion from malloc/init to
>> new/constructor with try/catch - I'll need to dig into this further.
>
>If you are mixing exceptions and return codes, you aren't really making 
>a fair comparison.  It is very likely you could improve the performance 
>in other ways, such as a specialised allocator.  If your application was 
>designed to use exceptions throughout, I bet you would see a performance 
>improvement.

Unfortunately, this is a 60,000+ SLOC application and making such a change
wouldn't be useful - there are only a half dozen or so dynamic allocations
in the entire application, and I'm working on eliminating most of those
(or moving them to the application initialization phase).

Let me be clear, I never actually took an exception in the test I described above;
the sole difference was changing the 

   buf = malloc(XXX); if (buf == NULL) { YYY}  

test to

   try {buf = new uint8[XXX];} catch (std::exception& e) { YYY }

(and of course, the corresponding 'free()' <-> 'delete []' changes).

The exception was never thrown during the test (but the test function was called
about 500,000 times while the processor code simulated 43,000,000 mainframe instructions)
over a wall-time duration of about 25 seconds.

Since there is a hard (and relatively small) limit on the number of objects of
the type in the test that can be allocated during a run (basically one per simulated
processor and a couple of extras), I plan on overloading operator new for the
object and using a startup-allocated pool of objects to handle object allocation.  This
will eliminate both checks.

Similar mechanisms will be used for all other run-time (vs. initialization time)
allocations.

scott

[toc] | [prev] | [next] | [standalone]


#13641

FromIan Collins <ian-news@hotmail.com>
Date2012-01-29 12:22 +1300
Message-ID<9ojea4F8j0U16@mid.individual.net>
In reply to#13637
On 01/29/12 11:49 AM, Scott Lurndal wrote:
> Ian Collins<ian-news@hotmail.com>  writes:
>> On 01/28/12 05:18 PM, Scott Lurndal wrote:
>
>>> However, in this case (modeling a physical device), the best determination
>>> of how to present the failure  can be made as close to the cause of the
>>> exception as possible.   I would think that for most applications that
>>> can actually recover from an error (as opposed to just catching std::exception
>>> at the top level, printing a message, and exiting), keeping the recovery action
>>> as close to the code that actually failed makes recovery much simpler.
>>
>> It may well be, but the catch and the throw my still be several calls
>> away.  Using nested small functions is much cleaner with exceptions than
>> with return codes.  In your example you return the state in the object
>> passed.  An exception based design may well pass the state in an
>> application specific exception.
>
> Which  will have additional  overhead to allocate, construct,
> destroy and deallocate the application class derived from std::exception, nicht wahr?

Only in the exceptional circumstances where one is thrown.  As I said, 
the state has to be returned somewhere.

> I think you would find that "small nested functions" is exactly what is
> used, and in this case, the object passed doesn't necessary _return_ the state
> passed so much as provide a channel for returning the state to the final
> receipient.
>
> Now in the core processor simulation code sigsetjmp/siglongjmp are used to reset
> the simulated processor to the start of the instruction processing loop when
> an exception occurs executing an instruction (an address error, invalid instruction,
> etc).   These could possibly be converted to exceptions, but I'm quite sure that
> the performance would be worse and the RAS characteristics of the application
> wouldn't change appreciably.

By using exceptions, you are able to utilise the full power of the 
language, such as RAII which out of band jumps preclude.

One point I have been trying to make is bolting exceptions onto an 
existing design is seldom a good idea.  Neither is having to take them 
out, which was a situation I once found myself in!  Error handling is a 
fundamental part of a system's design and mixing paradigms invariably 
ends in tears.

> I remember reading Tom Cargill's article on exceptions back when they were
> introduced to the language - I think many of his points still apply - exceptions
> are not a universal panacea and careful analysis of all codepaths need be done
> to prevent memory leaks or access to deallocated data when exceptions are being
> thrown.

This is true and the language provides us with the tools to achieve 
this. Tools which cannot be used with out of band jumps!

>    The same caveats, of course, apply to setjmp/longjmp as well, but I
> don't need to allocate an exception object (just set one of 10 bits in a member
> field of the current 'this' when the longjmp is issued; the jmp_buf also a member
> of the current object).

The cost of constructing an exception object are far outweighed by the 
cost of throwing it *in the exceptional case*.

>>>> The catch is also the reason for all the extra code, constructing and
>>>> destructing a temporary std::exception object.  The actual exception
>>>> handling part of the code is this bit:
>>>
>>> Yet creating and destroying a temporary std::exception object also counts in
>>> terms of both extra cycles and code footprint.   Both of which impact
>>> performance (generally negatively).
>>
>> Only if the exceptional condition occurs.  The normal path of execution
>> will not be impacted (and will be cleaner and faster than the error
>> checking case).
>
> I haven't seen this in practice, but then my sole exposure to C++ code
> has been in the Operating Systems/Microkernel/Hypervisor area none of which
> used exceptions (most of which predated exceptions :-), aside from one
> application at a major internet certification authority, which also predated
> exceptions.

That's where our experiences diverge, I've been comparing the 
performance of exceptions on various platforms for many years and I've 
found exceptions are generally faster (always on the Unix and Linux 
platforms I use).  From my perspective, the exceptions vs error returns 
argument was settled long ago.

> Let me be clear, I never actually took an exception in the test I described above;
> the sole difference was changing the
>
>     buf = malloc(XXX); if (buf == NULL) { YYY}
>
> test to
>
>     try {buf = new uint8[XXX];} catch (std::exception&  e) { YYY }
>
> (and of course, the corresponding 'free()'<->  'delete []' changes).

You have introduced two variables, exceptions and new.  Try eliminating 
both.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#13609

Fromscott@slp53.sl.home (Scott Lurndal)
Date2012-01-27 20:16 +0000
Message-ID<MCDUq.107191$487.97@news.usenetserver.com>
In reply to#13604
Ian Collins <ian-news@hotmail.com> writes:
>On 01/27/12 09:55 AM, Scott Lurndal wrote:
>> Cholo Lennon<chololennon@hotmail.com>  writes:
>>> On 26/01/2012 16:24, Scott Lurndal wrote:
>>>> The readability of C++ seems to get worse with each new version of the
>>>> standard.   Once the<XXX>   elements (static/dynamic casts, templates) were added
>>>> to the language, it became worse than perl for readability.
>>>
>>> Really? Do you think C++ cast operators go against readability? For me
>>> is the opposite: At glance, for example, they give you more information
>>> than the traditional C cast and, as a result, they are (IMHO) more readable.
>>>
>>
>> Buenas,
>>
>>     I think they may provide better _maintainability_ at the expense of _readability_.
>>
>>     It may also be that for someone coming from a C background (starting in 1978),
>> the dynamic/static cast syntax just looks alien and out of place.
>>
>>     Templates and exceptions on the other hand, have a distinct impact on code size
>> (thus icache footprint, thus performance).
>
>The only performance impact I have ever measured from the use of 
>exceptions is improvement.  I have been testing compilers since the mid 
>90s and I have only found one compiler/platform (that compiler refused 
>to inline any function that could throw) where exceptions had a 
>detrimental impact on performance.
>
>In overall performance terms, templates are no worse and often a 
>significant improvement over the direct C equivalent (macros) because 
>they aren't necessary inlined.  They can also provide significant 
>performance improvements over another C alternative, the use of void* 
>and function pointers (sorting being the classic example).
>
>Yes you can end up with multiple instances of class methods, but that is 
>the price you pay for type safety.  Anyway, what proportion of a decent 
>sized project would that represent?  For containers of pointers one can 
>easily use inline wrappers round a container of void* to avoid bloat 
>while retaining type safety.  In most code I have seen, containers of T* 
>are more numerous than containers of T
>
>Thus with contemporary tools, the twin myths of exception performance 
>and template code bloat are just that: myths.

Unless you are writing an operating system or hypervisor where every byte
counts.

scott

[toc] | [prev] | [next] | [standalone]


#13611

FromIan Collins <ian-news@hotmail.com>
Date2012-01-28 10:01 +1300
Message-ID<9oghluF8j0U3@mid.individual.net>
In reply to#13609
On 01/28/12 09:16 AM, Scott Lurndal wrote:
> Ian Collins<ian-news@hotmail.com>  writes:
>> On 01/27/12 09:55 AM, Scott Lurndal wrote:
>>> Cholo Lennon<chololennon@hotmail.com>   writes:
>>>> On 26/01/2012 16:24, Scott Lurndal wrote:
>>>>> The readability of C++ seems to get worse with each new version of the
>>>>> standard.   Once the<XXX>    elements (static/dynamic casts, templates) were added
>>>>> to the language, it became worse than perl for readability.
>>>>
>>>> Really? Do you think C++ cast operators go against readability? For me
>>>> is the opposite: At glance, for example, they give you more information
>>>> than the traditional C cast and, as a result, they are (IMHO) more readable.
>>>>
>>>
>>> Buenas,
>>>
>>>      I think they may provide better _maintainability_ at the expense of _readability_.
>>>
>>>      It may also be that for someone coming from a C background (starting in 1978),
>>> the dynamic/static cast syntax just looks alien and out of place.
>>>
>>>      Templates and exceptions on the other hand, have a distinct impact on code size
>>> (thus icache footprint, thus performance).
>>
>> The only performance impact I have ever measured from the use of
>> exceptions is improvement.  I have been testing compilers since the mid
>> 90s and I have only found one compiler/platform (that compiler refused
>> to inline any function that could throw) where exceptions had a
>> detrimental impact on performance.
>>
>> In overall performance terms, templates are no worse and often a
>> significant improvement over the direct C equivalent (macros) because
>> they aren't necessary inlined.  They can also provide significant
>> performance improvements over another C alternative, the use of void*
>> and function pointers (sorting being the classic example).
>>
>> Yes you can end up with multiple instances of class methods, but that is
>> the price you pay for type safety.  Anyway, what proportion of a decent
>> sized project would that represent?  For containers of pointers one can
>> easily use inline wrappers round a container of void* to avoid bloat
>> while retaining type safety.  In most code I have seen, containers of T*
>> are more numerous than containers of T
>>
>> Thus with contemporary tools, the twin myths of exception performance
>> and template code bloat are just that: myths.
>
> Unless you are writing an operating system or hypervisor where every byte
> counts.

A large proportion of my work is in embedded devices, where the byte 
count is even more important!

These days of low cost, plentiful RAM, the most important factor in 
hypervisor or operating system is performance, not code size.

As I said above, if code size is an an issue, there are well known 
coding practices that can be employed to minimise it.

There are also techniques used by embedded tool chains to minimise code 
size.  However more often than not these techniques are detrimental to 
performance and should only be employed when physical resources are tight.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#13625

FromJuha Nieminen <nospam@thanks.invalid>
Date2012-01-28 16:00 +0000
Message-ID<4f241b9b$0$3110$7b1e8fa0@news.nbl.fi>
In reply to#13595
Scott Lurndal <scott@slp53.sl.home> wrote:
> The readability of C++ seems to get worse with each new version of the
> standard.   Once the <XXX> elements (static/dynamic casts, templates) were added
> to the language, it became worse than perl for readability.

  I believe you are confusing readability with brevity. Not the same
thing.

[toc] | [prev] | [next] | [standalone]


#13219

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2012-01-10 21:42 +0000
Message-ID<slrnjgpc62.1ls.grahn+nntp@frailea.sa.invalid>
In reply to#13209
On Tue, 2012-01-10, AD wrote:
> I kid you not, I found this trash in a real project:
>
> //Remove texture from the the stack and try to unload from memory
> void resourceManager::popTexture(const char* nickName)
> {
> 	BOOL removed = false;
> 	for  (std::vector<texture*>::iterator itr = textures.begin(); itr !=
> textures.end();)
> 	{
> 		if ( (*itr)->nickName == nickName )
> 		{

I don't see anything unusually bad about it. I assume there's a itr++
elsewhere, and that texture::nickName is a std::string.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


Page 4 of 5 — ← Prev page 1 2 3 [4] 5  Next page →

Back to top | Article view | comp.lang.c++


csiph-web