I just wanted to make sure core had seen this blog post (with comments narrowing down the scope) about #inject, #each, and #times (at least) being slower on OS X (http://antoniocangiano.com/2008/03/25/inject- each-and-times-methods-much-slower-in-ruby-19/). I believe I'm correct in finding that revision 15124 is when those methods went from faster than 1.8.6 to much slower.
In message "Re: some Enumerable methods slower in 1.9 on OS X after revision 15124" on Wed, 26 Mar 2008 23:32:12 +0900, Chris Shea <cms...@gmail.com> writes:
|I just wanted to make sure core had seen this blog post (with comments |narrowing down the scope) about #inject, #each, and #times (at least) |being slower on OS X (http://antoniocangiano.com/2008/03/25/inject- |each-and-times-methods-much-slower-in-ruby-19/). I believe I'm correct |in finding that revision 15124 is when those methods went from faster |than 1.8.6 to much slower.
It seems that sigsetjmp() is significantly slower on OS X. I contacted Nobu about this issue. I believe he will address soon.
At Thu, 27 Mar 2008 05:20:57 +0900, Yukihiro Matsumoto wrote in [ruby-core:16037]:
> |I just wanted to make sure core had seen this blog post (with comments > |narrowing down the scope) about #inject, #each, and #times (at least) > |being slower on OS X (http://antoniocangiano.com/2008/03/25/inject- > |each-and-times-methods-much-slower-in-ruby-19/). I believe I'm correct > |in finding that revision 15124 is when those methods went from faster > |than 1.8.6 to much slower.
> It seems that sigsetjmp() is significantly slower on OS X. I > contacted Nobu about this issue. I believe he will address soon.
No, r15124 changed to use setjmp instead of _setjmp if sigsetjmp exists, so sigsetjmp isn't used as well as earlier.
The setjmp()/longjmp() pairs save and restore the signal mask while _setjmp()/_longjmp() pairs save and restore only the register set and the stack. (See sigprocmask(2).)
also:
The sigsetjmp()/siglongjmp() function pairs save and restore the signal mask if the argument savemask is non-zero; otherwise, only the register set and the stack are saved.
Should the priority be _setjmp > sigsetjmp > setjmp?
On Thu, Mar 27, 2008 at 02:26:51PM +0900, Nobuyoshi Nakada wrote: > Should the priority be _setjmp > sigsetjmp > setjmp?
I think it may depend on the platform. I ran across this the other day while trying to decide whether I could afford the overhead of a call to rb_protect():
One of the 'big wins' I discovered was to rebuild perl so that it used setjmp instead of the default sigsetjmp. This gave about an 18% performance boost. It turns out that the perl interpreter calls sigsetjmp every time it enters a new block scope, and the libexacct module does this a lot, which is why the setjmp/sigsetjmp difference is so noticeable. I wrote a micro benchmark to time how long setjmp and sigsetjmp took.
At Thu, 27 Mar 2008 22:31:31 +0900, Paul Brannan wrote in [ruby-core:16049]:
> On Thu, Mar 27, 2008 at 02:26:51PM +0900, Nobuyoshi Nakada wrote: > > Should the priority be _setjmp > sigsetjmp > setjmp?
> I think it may depend on the platform. I ran across this the other day > while trying to decide whether I could afford the overhead of a call to > rb_protect():
> It seems there exist platforms where setjmp is preferable over > sigsetjmp with the second parameter set to 0.
Thank you for the info, it's interesting. On cygwin, sigsetjmp() always stores the signal mask regardless the SAVEMASK value, too. The parameter works as RESTOREMASK instead.
This patch makes: * if --with-setjmp-type configure option is given, use its value, * if _setjmp is available, use it, * if sigsetjmp is N/A, use setjmp, * use setjmp on Solaris and Cygwin, or sigsetjmp on others.
Any more reasonable solutions?
Index: stable/configure.in =================================================================== --- stable/configure.in (revision 15830) +++ stable/configure.in (working copy) @@ -573,4 +573,41 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid mktime timegm gettimeofday\ cosh sinh tanh round setuid setgid setenv unsetenv) + +AC_MSG_CHECKING(for setjmp type) +AC_ARG_WITH(setjmp-type, + [ --with-setjmp-type select setjmp type], [ + case $withval in + _setjmp) setjmp_prefix=_;; + sigsetjmp) setjmp_prefix=sig;; + setjmp) setjmp_prefix=;; + '') unset setjmp_prefix;; + *) AC_MSG_ERROR(invalid setjmp type: $withval);; + esac], [unset setjmp_prefix]) +if test ${setjmp_prefix+set}; then + if test "${setjmp_prefix}" && eval test '$ac_cv_'${setjmp_prefix}setjmp = no; then + AC_MSG_ERROR(${setjmp_prefix}setjmp is not available) + fi +elif test "$ac_cv_func__setjmp" = yes; then + setjmp_prefix=_ +elif test "$ac_cv_func_sigsetjmp" = yes; then + case $target_os in + solaris*|cygwin*) + setjmp_prefix=;; + *) + setjmp_prefix=sig;; + esac +else + setjmp_prefix= +fi +if test $setjmp_prefix = sig; then + setjmp_sigmask=yes +else + unset setjmp_sigmask +fi +AC_MSG_RESULT(${setjmp_prefix}setjmp) +AC_DEFINE_UNQUOTED([RUBY_SETJMP(env)], [${setjmp_prefix}setjmp(env${setjmp_sigmask+,0})]) +AC_DEFINE_UNQUOTED([RUBY_LONGJMP(env,val)], [${setjmp_prefix}longjmp(env,val)]) +AC_DEFINE_UNQUOTED(RUBY_JMP_BUF, ${setjmp_sigmask+${setjmp_prefix}}jmp_buf) + AC_ARG_ENABLE(setreuid, [ --enable-setreuid use setreuid()/setregid() according to need even if obsolete.], Index: stable/node.h =================================================================== --- stable/node.h (revision 15830) +++ stable/node.h (working copy) @@ -388,5 +388,5 @@ typedef struct { } rb_jmpbuf_t[1]; #else -typedef jmp_buf rb_jmpbuf_t; +typedef RUBY_JMP_BUF rb_jmpbuf_t; #endif
Nobuyoshi Nakada wrote: > This patch makes: > * if --with-setjmp-type configure option is given, use its value, > * if _setjmp is available, use it, > * if sigsetjmp is N/A, use setjmp, > * use setjmp on Solaris and Cygwin, or sigsetjmp on others.
> Any more reasonable solutions?
This seems reasonable to me.
Also, I wonder if there is any benefit to __builtin_setjmp instead of _setjmp?
Also, just thinking, I wonder how hard it would be to make use of dwarf2 exceptions on gcc via unwind.h?
On Tue, Apr 01, 2008 at 03:27:51AM +0900, Nobuyoshi Nakada wrote: > Hi,
> At Mon, 31 Mar 2008 22:07:03 +0900, > Paul Brannan wrote in [ruby-core:16086]: > > Also, I wonder if there is any benefit to __builtin_setjmp instead of > > _setjmp?
> Unfortunately,
> error: '__builtin_longjmp' second argument must be 1
See attached for a workaround, but I was not able to measure any performance benefit on gcc 3.3. :(
(but I'm also not sure how to construct a good benchmark where the method call overhead doesn't dwarf what I'm trying to measure)
> it seems not be able to pass a variable. And combination with > _longjmp caused SEGV.
> > Also, just thinking, I wonder how hard it would be to make use of dwarf2 > > exceptions on gcc via unwind.h?
> How faster is it?
I don't know; we'd have to try it and find out.
No one seems to have benchmarks, just blanket statements like "dwarf2 exceptions are faster than sjlj for non-exceptional cases".