大模型“四虎”出山,亮相 4 月 QCon 北京。 了解详情
写点什么

Yammer 从 Scala 转向 Java

  • 2012-02-01
  • 本文字数:2600 字

    阅读完需:约 9 分钟

近日,由 Yammer 雇员 Coda Hale 发给 Typesafe 的 Scala 商业管理层的邮件通过 YCombinator 被泄漏出来并在 GitHub 上刊出。该邮件确认 Yammer 正在将其基础设施栈从 Scala 迁回至 Java,原因在于 Scala 的复杂性与性能问题。

Yammer 的公关 Shelley Risk 向 InfoQ 证实该邮件只代表 Coda Hale 的个人意见而非 Yammer 的官方声明;随后,Coda Hale 又在 http://codahale.com/the-rest-of-the-story/ 上发表了一篇文章。在该文章中,Coda 澄清说这个消息是来自于 Donald Fischer( Typesafe 的 CEO)对早前一个 tweet 的回复。

更新:近日,Yammer 已经发布了声明,宣布对该问题的立场,声明证实了上述猜测。声明还指出任何语言都会有瑕疵(不仅仅是 Scala),该邮件只不过是尝试提出一些建议以改进 Scala 的性能与其他问题。最后,声明说到在构建任何高性能项目时(Scala 是其产品环境)都有一些问题需要解决;该邮件旨在帮助 Scala 不断改进。

虽然 Coda 并未打算公开该邮件,但他通过 Gist(后来被删除了)将其放到了 GitHub 上以获得其他朋友的反馈;然而,邮件内容后来被共享出来并得到了大范围传播。

回到 2010 年 8 月,Coda 在 Yammer Engineering 博客上说他们将要转向 Scala 。其目标是继续运行在 JVM(出于性能原因)上,这个转变的结果就是减少了约 50% 的代码:

Artie 最初的原型采用 Java 编写,但在一个周末的试验中,我尝试使用 Scala 2.8 重新实现一次。一天后,代码行数减少了约一半,并添加了几个特性。我震惊了,Java 开发者很容易找,但 Scala 团队却能完成更多工作

一年过后,这个决定发生了变化

目前在 Yammer,我们正在将基础设施迁回至 Java,同时以遗留库的形式继续对 Scala 提供支持。这个过程并不是那么急,我们刚刚开始,但需要很长时间。本质在于使用 Scala 而非 Java 作为我们的默认语言所产生的摩擦和复杂性并未被足够的生产力提升或是维护工作的减少而抵消。我们或许还会在产品中使用 Scala,但主要的开发将会使用 Java。

Stephen Colebourne(近日发表了文章 Is Scala the new EJB2?)对这封邮件做了点评,其要点总结如下:

  • 作为一门语言,Scala 中有很多颇具见地的想法。但它是门非常复杂的语言。
  • 除了 Scala 所引入的概念与具体实现外,要想编写地道的 Scala 还有一个文化的问题,有时突然就蹦出来一个最佳实践:完全不管不顾社区。
  • 我当然知道学习(以及教授)Scala 的困难程度与重要性。因为我们不可能在没人学习 Scala 的情况下找到人,这个事实非常重要。
  • 构建工具链导致开发很不舒服。这主要是因为 SBT 导致了 Maven 与 Ant 的边缘化——而他们是 Java 生态圈中的两个主要的构建工具。
  • 每个主要的 Scala 发布都不兼容于之前的版本,这导致 Scala 开发者总是在开发新的库并重新发明轮子。
  • 借助于分析与检查字节码,我们可以通过采用一些简单的规则实现 100 倍的改进:
    • 不要使用 for 循环
    • 不要使用 scala.collection.mutable
    • 不要使用 scala.collection.immutable
    • 总是使用 private[this]
    • 不要使用闭包
  • 我和开发团队讨论了这个问题(迁回至 Java),并且演示了两个代码基,结果是大家普遍同意进行切换。毫无疑问,我们肯定对 Scala 的某些方面还不太熟悉,但这不足以让我们还固守在 Scala 上。

其中一些问题可能不太重要(比如说,一门语言越流行,那么雇佣的开发者的经验就会越多),其中一些是根据经验来测试的。比如说,其中一条建议就是不要使用 for 循环。这可以通过如下代码进行测试:

复制代码
<pre>
scala>
var start = System.currentTimeMillis();
var total = 0;for(i <- 0 until 100000) { total += i };
var end = System.currentTimeMillis();
println(end-start);
println(total);
114
scala>
scala<
var start = System.currentTimeMillis();
var total = 0;var i=0;while(i < 100000) { i=i+1;total += i };
var end = System.currentTimeMillis();
println(end-start);
println(total);
8
</pre>

这里使用 for 循环(与"until"模式,很多 Scala 程序员都习惯这么用)要比对应的 while 循环慢很多,虽然使用 while 循环的可读性差一些。同样循环的 Java 实现对于 for 和 while 来说都是 2ms。

我们做的另一个测试是通过从一个包含 Integer 对象的数据集合中加载来看看可变 map 的性能(这可以在 Java 与 Scala 中进行对比,装箱的损耗应该差不多)。

复制代码
<pre>
scala>
val m = new scala.collection.mutable.HashMap[Int,Int];
var i = 0;
var start = System.currentTimeMillis();
while(i<100000) { i=i+1;m.put(i,i);};
var end = System.currentTimeMillis();
println(end-start);
println(m.size)
101
scala>
val m = new java.util.HashMap[Int,Int];
var i = 0;
var start = System.currentTimeMillis();
while(i<100000) { i=i+1;m.put(i,i);};
var end = System.currentTimeMillis();
println(end-start);
println(m.size)
28
scala>
val m = new java.util.concurrent.ConcurrentHashMap[Int,Int];
var i = 0;
var start = System.currentTimeMillis();
while(i<100000) { i=i+1;m.put(i,i);};
var end = System.currentTimeMillis();
println(end-start);
println(m.size)
55
</pre>

与 java.util.HashMap 相比,性能是相同的,与 java.util.concurrent.ConcurrentHashMap 相比,Java 的速度要比 Scala 快一倍。Java 集合类超越了 Scala(以上测试基于 OSX JVM 1.6.0_29 与 Scala 2.9.1,在文本撰写之际的最新版本)。

但遗憾的是,在 Scala 库 API 中有很多 Scala 集合,他们需要通过代码中的隐式转换从 Java 对象类型转换为 Scala 对象类型。出于性能原因,这需要大量的重写。

如果 Scala 编译器通过 invokedynamic 生成代码,那么闭包(lambdas)的性能还会得到改进,这是后续版本的 Scala 将会做的事情。此外,在 JDK 8 中(将会给 Java 带来 native lambdas 与 method handles)将会有很多的性能改进,这些改进都可以为 Scala 所用。

最后,Scala 在解决版本之间的不兼容问题上面临着越来越多的压力(不仅仅是2.9.2 与2.9.3 之间的小改进)。Typesafe 并未发布Scala 未来路线图的官方声明,也没有说明何时才会有稳定的二进制版本能够实现不同版本之间代码的兼容。如果能够实现向后兼容,那么就会有更多稳定的库出现,并且会形成一个社区仓库,这对未来有志于使用Scala 的开发者将大有裨益。

查看英文原文: Yammer Moving from Scala to Java

2012-02-01 04:285916
用户头像

发布了 88 篇内容, 共 265.4 次阅读, 收获喜欢 8 次。

关注

评论

发布
暂无评论
发现更多内容

Tomcat异常: Unable to process Jar entry [module-info.class] from Jar

小马哥

Java maven 七日更 二月春节不断更

Elasticsearch dynamic mapping

escray

elastic 七日更 死磕Elasticsearch 60天通过Elastic认证考试 2月春节不断更

深入理解gradle中的task

程序那些事

Java maven Gradle 程序那些事 构建工具

数字资产助力未来十年打赢数字经济战

CECBC

数字经济

中国科学家突破区块链核心技术

CECBC

区块链

机器学习笔记之:

Nydia

【LeetCode】最大连续1的个数Java题解

Albert

算法 LeetCode 2月春节不断更

公路交通区块链技术的痛点问题和典型场景应用

CECBC

区块链

Idea应用启动时WEB-INF/lib无效标记问题处理

程序员架构进阶

Java IntelliJ IDEA 七日更 2月春节不断更

10. 比找女朋友还难的技术点,Python 面向对象

梦想橡皮擦

Python 2月春节不断更 python入门

什么是MySQL数据库?看这一篇干货文章就够了!

我是哪吒

学习 程序员 后端 MySQ 2月春节不断更

Elasticsearch Mapping Index索引

escray

elastic 七日更 死磕Elasticsearch 60天通过Elastic认证考试 2月春节不断更

【STM32】串口通信出现乱码(使用官方标准库)

AXYZdong

硬件 stm32 2月春节不断更

工作学习累了?试试 GitHub 上的那些简单易学的游戏项目吧!

JackTian

GitHub 开源 游戏 2月春节不断更

诊所数字化从预约开始

boshi

数字化医疗 七日更 线上预约

记一次有意思的微信视频号直播

小匚

产品经理

【译文】工作六年后,我对软件开发的认知转变

Zhendong

程序员 软件开发

面试官系列:你对Spring事件发布和广播监听有了解吗?

后台技术汇

面试 2月春节不断更

《我们脑中挥之不去的问题》 - 卓克科普(3)

石云升

读书笔记 科普 2月春节不断更

今日出门

Nydia

JUnit速查手册

jiangling500

Java JUnit

翻译:《实用的Python编程》01_03_Numbers

codists

Python

年终述职PPT(996一年,怎么会什么都没干!)

鲁米

年终总结

日记 2021年2月15日(周一)

Changing Lin

2月春节不断更

week12-homework

J

面向对象设计原则

引花眠

面向对象设计原则

深入 Python 解释器源码,我终于搞明白了字符串驻留的原理!

Python猫

Python 编程

华为 MPLS的数据转发流程

艺博东

华为

保持模块的兼容性

Rayjun

go modules Go 语言

松耦合

sinsy

设计模式 RabbitMQ

ElasticSearch.02 - 安装

insight

elasticsearch 2月春节不断更

Yammer从Scala转向Java_Java_Alex Blewitt_InfoQ精选文章