Bill Allombert on Tue, 25 Aug 2009 14:44:57 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: TRY/CATCH is unnecessarily slow on OS X


On Sat, Aug 15, 2009 at 01:45:18AM +0200, Lorenz Minder wrote:
> Hi,
> 
> The PARI TRY/CATCH exception handling is currently very slow on
> Mac OS X (and probably *BSD, although I haven't checked that).  I don't 
> know if Linux is affected but quite possibly not.  

Hello Lorenz,
Thanks for reporting this issue.

> How slow is it?  Agonizingly slow.  The attached "except.cc" computes 
> "gsqrt(2)" repeatedly, once with each call wrapped into a CATCH/TRY 
> block and once without the wrapping.  With error checking, it's slower 
> by an order of magnitude:
> 
>         pari_perform$ time ./except n   # No error checking.
> 
>         real    0m0.700s
>         user    0m0.694s
>         sys     0m0.005s
>         pari_perform$ time ./except p   # W/ PARI exception handling.
> 
>         real    0m8.466s
>         user    0m5.799s
>         sys     0m2.660s

On my amd64-linux laptop I get:
%time ./expect n
./expect n  0,71s user 0,00s system 99% cpu 0,712 total
%time ./expect p
./expect p  1,23s user 0,00s system 100% cpu 1,226 total

This is still slow but more bearable.

> Some would probably argue that not every tiny call must be wrapped into
> a CATCH/TRY-block, but the fact is that doing this is sometimes 
> necessary, e.g., for wrapper libraries, or if you cannot or don't want
> to reuse the PARI error handling mechanisms in your C program.

Note that when using TRY/CATCH, you are effectively using the PARI error
handling mechanism.

> Why is it so slow?  The problem is that the Mac OS X version of 
> setjmp/longjmp saves and restores the signal mask, which appears to take 
> an insane amount of time.  Assuming that this is not necessary (if it 
> is, I think you have a bug on SysV), it is better to use a variant of 
> setjmp/longjmp that does not do this. Use _setjmp/_longjmp or possibly 
> sigsetjmp(,0)/siglongjmp() instead.

I have to agree that all systems should behave the same.
However my understanding of POSIX.1 is that setjmp/longjmp 
must not save and restore the signal mask, and non POSIX systems
are not required to carry sigsetjmp/siglongjmp.

> The attached patch does this as a proof of concept, and with it applied, 
> I get much better behaviour:
> 
>         pari_perform$ time ./except n
> 
>         real    0m0.700s
>         user    0m0.695s
>         sys     0m0.004s
>         pari_perform$ time ./except p
> 
>         real    0m0.810s
>         user    0m0.804s
>         sys     0m0.005s
> 
> This patch breaks systems that do not have _setjmp(), so you probably 
> have to test for its existence in Configure.

On my laptop, TRY/CATCH incurr a 80% penalty on the running time. We should do
more timings.

Cheers,
Bill.