Ruby 表现优于 Java 的案例

Case of Ruby performing better than Java

我正在做一个关于 Ruby 生态系统的演讲,目标人群是 Java。

尽管我会强调提高生产力的时间,较慢仍然可以足够快,但这会很好如果我能想出一个基准,表明 Ruby 在某种数字运算中表现优于 Java,一旦问题出现,为了双关语。


不幸的是,经过数小时的搜索和实验,我仍然一无所获。

谁能想出一个基准来表明事物并非完全黑白分明?

理想情况下,它应该将最新版本的 java 1.6/1.8 与最新版本的 进行比较小胖。任何涉及 rubinius/jruby 的例子也很受欢迎。

我认为您不会找到任何东西。说到优化,Ruby和Java其实很相似,两者的主要痛点是盒装对象和动态方法调度,它们都继承自Smalltalk(Ruby直接, Java 通过其 main inspiration Objective-C). And the Java VMs are quite simply the most advanced production execution environments for dynamically-dispatched OO languages there are. There may be some research stuff for Scheme, for example, that is even faster, but when it comes to production-ready industrial-strength implementations, Azul Zing, Oracle HotSpot, Oracle JRockit, IBM J9 和朋友轻松获胜。

因此,除非 Rubinius 人发明了 Smalltalk/Java 社区所忽视的东西,否则您最多只能获得相同的性能。

你最好的选择是不是数字处理而是文本处理。这就是 Ruby 的 Perl 遗产大放异彩的地方。大多数 Java 实现的正则表达式引擎性能不是很好(尽管它们正在变得更好),而 Onigmo 实际上相当不错(虽然不如 Perl 的好)。此外,Ruby 的字符编码独立字符串允许您消除对字符串的重新编码,而 Java 的字符串将始终必须编码为 UTF-16 或从 UTF-16 编码,除非输入和输出编码是 UTF-16,这是极不可能的。在Ruby中,你最多需要转码一次,即使你的输入和输出编码不同,你也可以将内部编码设置为与输入或输出编码相同,这样你只需要在输入或输出期间转码,但不能同时转码。

个例子 Ruby 与 C 竞争,并且由于 "everybody knows"™ C 比 Java 快,这肯定意味着 Ruby 比 Java 快,对吧? 对吗?

[实际上,找到 Ruby 优于 C 的示例可能更容易,因为动态优化,如推测内联、多态内联缓存、自适应优化,以及 "unsafe" 动态启用的优化典型的 C 实现中不存在优化。]

特别是 Rubinius 的 Hash class which is written in Ruby is not significantly slower than YARV's Hash class 是用 C 语言编写的

一个真正令人兴奋的例子是 JRuby+Truffle+Graal+TruffleC 可以 运行 YARV C 扩展 在 JVM 之上的 C 解释器中 (!!!)比 YARV 更快 运行 C 原生扩展:

[当然,后面这个例子其实是Truffle and Graal的威力的一个例子,即两个Java技术,不止是Ruby的一个例子.]

我曾经参加过一位 JRuby 开发人员的演讲,他指出他们从 JRuby 获得的基准测试比原生 Ruby 更好,这是因为 Sun/Oracle 花费了大量资金使 Hotspot 非常擅长 JIT 优化。

我怀疑一旦 JIT 有机会发挥其魔力,您可能会找到一些基准测试,其中 JRuby 与普通 Java 一样快。

所以尝试一个服务器应用程序,也许是一个网络应用程序,启动它并在开始测量性能之前至少运行一次代码。这应该意味着发生了 JIT,您可能会发现性能等同于普通的 Java.

即便如此,拖拉机也不是赛车。一个擅长赛跑,一个擅长拉犁。同样,存在不止一种语言也是有原因的。

我将最终使用一个简单的正则表达式示例 - /(foo|bar)*/,尝试匹配 'foobar' * n:


puts 'Done matching' if ('foobar' * 666).match(/(foo|bar)*/)

VS


import java.util.Collections;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class SimpleRegexTester {
    public static void main(String[] args) {
        String repeatedFooBar = String.join("", Collections.nCopies(666, "foobar"));
        Pattern p = Pattern.compile("(foo|bar)*");
        Matcher m = p.matcher(repeatedFooBar);

        if (m.matches())
            System.out.println("Done matching");
    }
}

它在技术上并没有更快,java 版本甚至不起作用(抛出 WhosebugError)。恕我直言,这个案例比 java 针对每种可能的情况进行了更好优化的概念要好得多。

这也让我很好地过渡到谈论代码简洁性,尤其是在我展示了 java8 之前的版本之后。