Oniguruma 的 Java 移植版让 JRuby 提速

阅读数:230 2007 年 12 月 2 日

话题:JavaRuby编程语言Ruby on Rails语言 & 开发架构

Ola Bini 报告说 Oniguruma 的移植版 Joni 已被合并入 JRuby 的代码主干

这是光辉的一天!Joni(Oniguruma 正则表达式引擎的 Java 移植版,Marcin 的出色成果)已经被合并入 JRuby 的代码主干。现在看起来工作得非常好。

JRuby 团队成员 Marcin Mielczynski 当初接下了将Oniguruma Regex引擎移植到 Java 代码的工作——Oniguruma 是 Ruby 1.9.x 中包含的正则表达式引擎。

总也说不完的JRuby与正则表达式(Regex)引擎之间的故事,这次总算画上了句号。早期的 JRuby 使用 Java 内建的 Regex 库(由 Java 1.4 引入)来实现 Ruby 正则表达式。虽然这是最简单的方案,不需要任何第三方库或者移植,但它也带来了一些问题,因此不适合 JRuby。由于 JRuby 目标是成为与 Ruby 1.8.x(及以后版本)兼容的实现,因此有必要支持同样的正则表达式。Java 内建的实现被发现不兼容,部分是因为算法中的实现细节让它不能处理某些表达式。Ola 解释了随后的步骤

为了解决这个问题,我们集成了 JRegex 作为替代。这是 JRuby 1.0 发布时带的引擎,现在用的也仍然是它。它工作得很好。对于一个用 Java 编写的引擎来说,它已经算快了,但还不够快。具体地说,它不支持对字符串的精确查找,不支持 fail-fast,而且该引擎要求我们把 byte[] 字符串转换成 char[] 或者 String。不尽理想。另一个问题是损害了与 MRI 的兼容性,特别是在多字节支持上。

所有这些问题应该也将会被 Joni 解决掉。Regex 性能过去是一个大问题(例子可见《在 JRuby on Rails 上构建 Oracle Mix 的收获》),Joni 看起来对此也有帮助。Charles Nutter用新的代码来检验了 REXML 的性能

在经过一系列基本的优化后,我们先前担忧的大多数关键表达式的性能都至少和 JRegex 一样,甚至要好很多,于是 Ola 花了几天时间完成了转换。Marcin 正继续在进行各种优化。我和 Ola 都已经试验过新的代码。看起来很不错。

Nutter 接着给出了合并代码前后的基准测试结果对比,数据显示出 Joni 代码带来了显著的速度提升。

这个问题也暴露出了很多 Ruby 实现共同面对的一个麻烦。Rubinius是大部分用 Ruby 编写的一个 Ruby 实现,它可以直接采用最简单的方案——包含 Oniguruma。但在 VM(如 JVM 和.NET)上完成的 Ruby 实现,如果要包含一个原生库,会让部署变得更加困难(它们必须为各平台发行专门的版本)。除此之外,Marcin 指出还存在其它集成问题

我们已经考虑过 [包含 Oniguruma]。有几个理由:

多线程:Oniguruma 在初始化代码范围表或者管理共享的 AST 节点(如 Character 类散列表)时,使用全局锁。Oniguruma 字节码解释器也使用线程锁(可以关闭该特性,但在 Java 中这项特性是自带的,而且混合异种线程和 Java 线程属于歪道)。

异常:很难从 segfaults 从恢复。把 Oniguruma 转换成 Ruby 异常也是一种丑陋的歪道。

JNI:JNI 要求本地数据与 VM 数据分离,因此所有的字符串、字节都要进行复制。

额外的二进制分发包:希望你编译时不会遇到什么麻烦:D
查看英文原文:Oniguruma Java port speeds up JRuby