Bill Allombert on Sat, 05 Sep 2009 13:49:03 +0200

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

Re: TRY/CATCH is unnecessarily slow on OS X

On Thu, Sep 03, 2009 at 08:43:44AM +0200, Lorenz Minder wrote:
> Hi,
> I find this surprising indeed.  I did a couple of runs with 64bit
> compiles on OS X and NetBSD, and I can't observe anything that bad when
> _setjmp / _longjmp is used.  (I get a ~20% slowdown or so relative to no
> error checking.  It's a bit more with Linux on G4, but still only ~30%.)
> The numbers are later in the mail.

Thanks, I will retry next week on more proper hardware.

> I went and checked the POSIX spec this afternoon.  These are the main

Was it the standard or the draft ? It would not be te only place they differ.

> points:
> 1) It is unspecified whether setjmp() saves the signal mask.  (They
>    don't say anything about that in the setjmp manpage itself, but
>    elsewhere they explicitly say it's unspecified.)
> 2) _setjmp() must not store the signal mask.
> 3) sigsetjmp(,0) does not have to store the signal mask, but it can.
>    sigsetjmp(,1) must store it.
> 4) They say new software should not use _setjmp, but rather sigsetjmp.
> I think that given that sigsetjmp(,0) may store the signal mask, the
> advice 4) seems dodgy.

What is worse, this is misleading: if you let out performance (which is 
not a POSIX concern), then the issue is that siglongjmp can restore the
signal mask even if one do not want to.

> > On my laptop, TRY/CATCH incurr a 80% penalty on the running time. We
> > should do more timings.
> Yes, indeed.  See also the bottom of this mail.
> BA:
> > On Mon, Aug 24, 2009 at 01:03:13AM -0700, Lorenz Minder wrote:
> > err_catch is only supposed to be used through the TRY/CATCH macros so this is
> > not an issue. What is more problematic is changing the type of DATA->env:
> > User code might do setjmp(GP_DATA->env) and be broken by the change.
> Ok, thanks for clarifying.

Actually I have a plan to remove GP_DATA->env entirely and add a call-back
(cb_pari_err_restore) that would handle recovery from error.
Please see bug #958 for detail. This is still very preliminary.

> > So maybe we could use _setjmp/_getjmp instead of sigsetjmp/siglongjmp.
> We can't use _longjmp() on a jmp_buf that has been created with setjmp()
> or vice versa, so I don't think this will work.  Looking at the code
> again, it seems that the setjmp(GP_DATA->env)/longjmp(GP_DATA->env)
> business is separate from the TRY/CATCH/err_catch() infrastructure, so
> one option would be only to change TRY/CATCH/err_catch() to use
> _setjmp/_longjmp and leave the GP_DATA->env stuff as is.  It would be
> wise, though, to make sure that "pari_setjmp(GP_DATA->env)" would cause
> a compile-time error, so as to avoid erroneous use of pari_setjmp().  I
> think that can be arranged.
> This assumes that setjmp(GP_DATA->env) is only called infrequently, and
> is hence not performance-critical. I believe this holds at least for how
> it's used in GP.
> What do you think?

err_catch only purpose is to implement the current stacked exceptions 
system which I find wholly inedequate and hope to replace.

Furthermore, TRY/CATCH is not documented currently, and mostly here 
to implement the gp trap() function, which has its load of problem.

Adding a call-back 'cb_pari_err_restore' seems a better solution.

> I was actually going to propose a small change that makes it possible
> for users to avoid anything setjmp()/longjmp() based, provided they can
> come up with a viable alternative.  The idea is as follows.

I think it would be better to provide the user with the mean to implement
their own TRY/CATCH alternative, and keep the setjmp()/longjmp() one
for internal libpari use. But the hard part with exceptions is to recover
from them safely and without leaking resource.