我对此很感兴趣,因为一些基准非常适合 erlang,例如基因测序。所以在http://benchmarksgame.alioth.debian.org/上,我做的第一件事是查看 C 和 Erlang 的反向补码实现,以及测试细节。我发现测试是有偏差的,因为它没有考虑 erlang 启动 VM /w 调度程序所需的时间,本地编译的 C 启动速度要快得多。这些基准衡量的方式基本上是:
time erl -noshell -s revcomp5 main < revcomp-input.txt
现在基准测试显示 Java 用了 1.4 秒,而 erlang /w HiPE 用了 11 秒。运行(单线程)Erlang 代码花了我 0.15 秒,如果不考虑启动 vm 的时间,实际工作负载只用了 3000 微秒( 0.003 秒)。
所以我不知道这是如何进行基准测试的,如果它做了 100 次,那么它是没有意义的,因为启动 erlang VM 的成本将是 x100。如果输入比给出的长很多,那是有道理的,但我在网页上看不到任何细节。为了使托管语言的基准测试更加公平,让代码(Erlang/Java)向 python(正在执行基准测试)发送一个 Unix 信号,表明它达到了启动功能。
现在抛开基准测试不谈,erlang VM 本质上只是在最后执行机器代码,Java VM 也是如此。因此,Erlang 中的数学运算不会比 Java 中花费更长的时间。
Erlang 不擅长的是需要经常改变的数据。例如链式块密码。假设您有字符“0123456789”,现在您的加密将前 2 个字符与 7 相异或,然后通过前两个相加的结果对接下来的两个字符进行异或,然后将前两个字符与当前减去的 2 个字符相异或,然后异或接下来的4个字符..等
因为 Erlang 中的对象是不可变的,这意味着每次改变它时都需要复制整个 char 数组。这就是为什么 erlang 支持称为 NIFS 的东西,它是你可以调用的 C 代码来解决这个确切的问题。事实上,Erlang 附带的所有加密(ssl、aes、blowfish..)和压缩(zlib、..)都是用 C 实现的,从 Erlang 调用 C 的成本也接近 0。
因此,使用 Erlang 可以两全其美,获得 C 的速度和 Erlang 的并行性。
如果我要以最快的方式实现反向补码,我将使用 C 编写变异代码,但使用 Erlang 编写并行代码。假设输入是无限的,我会让 Erlang 在 >
<<Line/binary, ">", Rest/binary>> = read_stream
Dispatch the block to the first available scheduler via round robin,由无限的 EC2 私有网络隐藏节点组成,每毫秒实时添加到集群中。
然后这些节点通过 NIFS 调用 C 进行处理(C 是 alioth 网站上最快的反向恭维实现),然后将输出发送回节点主控以发送到输入器。
为了在 Erlang 中实现所有这些,我必须像编写单线程程序一样编写代码,创建这段代码需要不到一天的时间。
要在 Java 中实现这一点,我必须编写单线程代码,我必须承担从托管调用到非托管调用的性能损失(因为我们显然将使用 C 实现来完成繁重的工作),然后重写以支持64 核。然后重写它以支持多个CPUS。然后再次重写它以支持集群。然后再次重写以修复内存问题。
简而言之,这就是 Erlang。