当前位置: 首页 > 工具软件 > Rubinius > 使用案例 >

Rubinius 1.1和GIL的未来

太叔景同
2023-12-01

Rubinius 1.1终于发布了(请访问在Rubinius网站或者项目的GitHub库取得下载,一睹为快,或使用用RVM安装)。Rubinius 1.1的发布说明列出了一长串内容,介绍了改进和bug修复的信息,此外还提到了不少有用的新增功能。Rubinius的调试器功能强、速度快,一直都让Rubinius引以为傲,在1.1版本增加了一些新的调试功能(摘自发布说明):

\
\
  • 新增调试器API和参考CLI调试器\
  • 新增heapdump功能,用于内存调试\
  • 新增用来检测不良扩展的代码。需要重新编译现有扩展\
  • 为VM和Ruby崩溃新增了‘rbx report’命令及相关支持\
\

要启用调试器,需要在命令行中加入(-Xdebug)开关,这样一来在启动时就可以直接引导你进入调试器命令行。另一种调用调试器的方式是通过调试器API:“require 'debugger'”,然后在代码中调用“Debugger.start”就可以进入调试器。

\

目前,Rubinius团队在忙于编写项目的文档,可以通过rbx docs命令来访问,打开浏览器浏览即可。

\

此外,性能问题也是关注的重点之一:

\
\
  • 增加自动对象实例变量打包(automatic object ivar packing)功能(提升内存利用率)\
  • 在JIT中可以使用block内嵌(block inlining)功能\
  • 实现新的GIL算法,防止线程饥饿死锁(starvation)\
\

新的GIL算法采用了和Python 3.2里重建的GIL一样的方法,不过在Rubinius 1.1中,GIL仍是存在的

\

在1.1发布之前,InfoQ连线了Rubinius的缔造者Evan Phoenix,询问Rubinius项目hydra分支的相关信息,该分支旨在构建一个没有GIL的VM。

\

InfoQ:关于在Rubinius里移除GIL,你的计划是怎样的?

\
\t我所采用的策略如下:

\1) 去掉GIL本身。这并不难,就是一个在几处被调用到的C++类而已。

\2) Rubinius已经按照线程局域和共享的数据结构把代码组织起来了。我为共享的数据结构增加了互斥体,还给大多数方法上了锁。对于某些地方,我上锁上得有点过头了,不过就现在的情况来说没什么问题。为了简化加锁的操作,我采用了一些C++技巧,比如使用了局域锁(scope lock),在处于相应作用域内部是,加解锁工作会自动完成。

\3) 在刚引入JIT的时候,为了确保GC操作的安全,我不得不编写代码,让垃圾回收器停止(VM)系统内的所有线程。这么做是因为JIT是和执行中的Ruby代码并发执行的。既然GIL还在使用,这部分代码也被干净地重用着。

\4) 一直以来我都使用RubySpec的线程测试规约(specs)来检测与修复线程相关的崩溃问题。这个方法很管用,因为这些测试规约重现了多种线程行为。多数修复都是围绕着确保线程能被妥善启动及清除来解决问题的。我使用互斥体和自旋锁(spinlock)的组合方案来保证同步。

\5) 现在我已经开始运行整个RubySpec套件来检查更多的挂起和崩溃故障。

\

InfoQ:关于在Rubinius里移除GIL,你的计划是怎样的?GIL是会完全消失,还是在围绕着扩展或者其它系统的领域仍然被保留下来呢?

\
\t对于使用扩展的部分是有可能(保留下来的),原因很简单,因为扩展并没有被设计成可以并发运行的。C扩展要访问GC对象,是通过句柄系统来完成的,这部分要实现线程安全不难。不过,因为C扩展使用了不一定线程安全的C库之类的东西,我们很有可能需要对此做好预防工作。

\可能的做法,就是为所有扩展方法的执行增加一个锁,或者给每个扩展增加一个锁,然后让这个扩展里的所有扩展方法共享。这样就能实现对访问共享数据的代码的隔离,并能带来些许性能提升。

\同时,每个扩展配一把锁的方案还能让扩展把自己的线程安全状态告诉系统,并让扩展忽略锁。很显然,这会变成对C API的一个扩展,但这确实是扩展作者们和我讨论过的事情。

\

Hydra分支会被合并到未来的Rubinius分支上,这样一来MRI 1.9.2会变成仅存的带GIL的Ruby VM;JRuby和IronRuby都没有GIL,而MacRuby也在前一段时间放弃了GIL

\

对GIL的功能和Ruby 1.9.x如何实现GIL的话题感兴趣的读者,可以看看Elise Huard关于GIL(GVL)的文章。

\

在Ruby(以及Python)里难以并行运行线程的问题,导致了许多开发者把目光转向基于事件和非阻塞I/O的解决方案,此外,使用多个OS进程来实现负载分布也是常用的策略。近来不少围绕Node.js非阻塞特性的热烈讨论也与此相关。

\

不过,一旦不带GIL的Ruby VM和并行Ruby线程成为主流,到底会变成什么样子呢?这个趋势还可能逆转吗?

\

查看英文原文:Rubinius 1.1 - and the Future of the GIL

 类似资料: