我们都知道在编译Ruby的时候你需要使用configure的 --disable-pthread参数,而在configure --disable-pthread 可以让你得到大约 30% 性能提高。本文将分析这些性能的提高原因并给出更好的建议。

咱们都知道在编译Ruby的时分你需求运用configure的 --disable-pthread参数。没错,在configure --disable-pthread 能够让你得到大约 30% 功能进步。可是,这是为什么呢?

让Ruby功能添加30%的改善办法剖析(ruby用法)  Ruby 性能 改进 第1张

一切的这一些咱们需求运用 strace 东西,这个东西能够打出一切的实在的操作体系的调用。

下面,是一段咱们测验的例程:

def make_thread
  Thread.new {
    a = []
    10_000_000.times {
      a << "a"
      a.pop
    }
  }
end

t = make_thread
t1 = make_thread

t.join
t1.join

假如咱们运用 strace 东西去测验 configure --enable-pthread 版别的Ruby引擎,那么咱们能够得到下面这样的成果:

22:46:16.706136 rt_sigprocmask(SIG_BLOCK, NULL, [], 8 ) = 0 <0.000004>
22:46:16.706177 rt_sigprocmask(SIG_BLOCK, NULL, [], 8 ) = 0 <0.000004>
22:46:16.706218 rt_sigprocmask(SIG_BLOCK, NULL, [], 8 ) = 0 <0.000004>
22:46:16.706259 rt_sigprocmask(SIG_BLOCK, NULL, [], 8 ) = 0 <0.000005>
22:46:16.706301 rt_sigprocmask(SIG_BLOCK, NULL, [], 8 ) = 0 <0.000004>
22:46:16.706342 rt_sigprocmask(SIG_BLOCK, NULL, [], 8 ) = 0 <0.000004>
22:46:16.706383 rt_sigprocmask(SIG_BLOCK, NULL, [], 8 ) = 0 <0.000004>

你会发现上面的sigprocmask 体系调用一页一页又一页地没完没了的。假如你用 strace -c,你会发现总共大约20,054,180 个sigprocmask体系调用。可是,假如你是在--disable-pthread 的Ruby版别下运转,你会发现底子没有那么多的sigprocmask 体系调用(只需 3 次,几乎便是大相径庭)

检查一下源代码

咱们知道 configure 是一个脚本,其主要用来创立一个 config.h 文件,其中有一大堆宏界说 defines ,这些宏界说决议了运用什么样的函数。所以,让咱们来比较一下版别 ./configure --enable-pthread 和版别./configure --disable-pthread的不同之处吧。

$ diff config.h config.h.pthread
> #define _REENTRANT 1
> #define _THREAD_SAFE 1
> #define HAVE_LIBPTHREAD 1
> #define HAVE_NANOSLEEP 1
> #define HAVE_GETCONTEXT 1
> #define HAVE_SETCONTEXT 1

好的,现在咱们再 grep 一下Ruby的源代码,咱们能够看到只需HAVE_[S/G]ETCONTEXT 被设置了,Ruby 就会调用setcontext() 和getcontext() 这两个体系调用来存取context 的状况,以便反常处理时的切换(经过EXEC_TAG)。

而假如 HAVE_[S/G]ETCONTEXT 没有被界说 的情况下,Ruby 会运用 _setjmp/_longjmp这两个体系调用。

咱们来看看 _setjmp/_longjmp 的man page:

… The _longjmp() and _setjmp() functions shall be equivalent to longjmp() and setjmp(), respectively, 
with the additional restriction that _longjmp() and _setjmp() shall not manipulate the signal mask…

还有setcontext /getcontext的 man page:

… uc_sigmask is the set of signals blocked in this context (see sigprocmask(2)) …

咱们能够看到 getcontext 调用每次都要调用sigprocmask 可是_setjmp 不会。

补丁

经过补丁增加了一个configure 的参数 --disable-ucontext 其能够让你封闭运用 setcontext或getcontext,你只需求像如下方法运用就好了。

./configure --disable-ucontext --enable-pthread

补丁下载:http://github.com/ice799/matzRuby/commit/0b9b69f9653782a33aee2b8937d405eae245b60c

假如你以这种方法编译Ruby,那么,你的程序的功能在同等条件下或许会有30%左右的提高。

【修改引荐】

  1. Ruby言语的发展趋势和启示
  2. Ruby on Rails为企业SOA做好预备了吗
  3. 脚本言语排行榜 PHP、Ruby和Python抢先
转载请说明出处
知优网 » 让Ruby功能添加30%的改善办法剖析(ruby用法)

发表评论

您需要后才能发表评论