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

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

  • 作为一门语言,Scala中有很多颇具见地的想法。但它是门非常复杂的语言。\u0026#xD;\n
  • 除了Scala所引入的概念与具体实现外,要想编写地道的Scala还有一个文化的问题,有时突然就蹦出来一个最佳实践:完全不管不顾社区。\u0026#xD;\n
  • 我当然知道学习(以及教授)Scala的困难程度与重要性。因为我们不可能在没人学习Scala的情况下找到人,这个事实非常重要。\u0026#xD;\n
  • 构建工具链导致开发很不舒服。这主要是因为SBT导致了Maven与Ant的边缘化——而他们是Java生态圈中的两个主要的构建工具。\u0026#xD;\n
  • 每个主要的Scala发布都不兼容于之前的版本,这导致Scala开发者总是在开发新的库并重新发明轮子。\u0026#xD;\n
  • 借助于分析与检查字节码,我们可以通过采用一些简单的规则实现100倍的改进:\u0026#xD;\n
    • 不要使用for循环\u0026#xD;\n
    • 不要使用scala.collection.mutable\u0026#xD;\n
    • 不要使用scala.collection.immutable\u0026#xD;\n
    • 总是使用private[this]\u0026#xD;\n
    • 不要使用闭包\u0026#xD;\n

    \u0026#xD;\n

  • 我和开发团队讨论了这个问题(迁回至Java),并且演示了两个代码基,结果是大家普遍同意进行切换。毫无疑问,我们肯定对Scala的某些方面还不太熟悉,但这不足以让我们还固守在Scala上。\u0026#xD;\n

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

\u0026#xD;\n

\u0026#xD;\n

\u0026#xD;\nscala\u0026gt;\u0026#xD;\n  var start = System.currentTimeMillis();\u0026#xD;\n  var total = 0;for(i \u0026lt;- 0 until 100000) { total += i };\u0026#xD;\n  var end = System.currentTimeMillis();\u0026#xD;\n  println(end-start);\u0026#xD;\n  println(total);\u0026#xD;\n114\u0026#xD;\nscala\u0026gt;\u0026#xD;\nscala\u0026lt; \u0026#xD;\n  var start = System.currentTimeMillis();\u0026#xD;\n  var total = 0;var i=0;while(i \u0026lt; 100000) { i=i+1;total += i };\u0026#xD;\n  var end = System.currentTimeMillis();\u0026#xD;\n  println(end-start);\u0026#xD;\n  println(total);\u0026#xD;\n8\u0026#xD;\n

\u0026#xD;\n

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

\u0026#xD;\n

\u0026#xD;\nscala\u0026gt;\u0026#xD;\n  val m = new scala.collection.mutable.HashMap[Int,Int]; \u0026#xD;\n  var i = 0;\u0026#xD;\n  var start = System.currentTimeMillis();\u0026#xD;\n  while(i\u0026lt;100000) { i=i+1;m.put(i,i);};\u0026#xD;\n  var end = System.currentTimeMillis();\u0026#xD;\n  println(end-start);\u0026#xD;\n  println(m.size)\u0026#xD;\n101\u0026#xD;\nscala\u0026gt;\u0026#xD;\n  val m = new java.util.HashMap[Int,Int]; \u0026#xD;\n  var i = 0;\u0026#xD;\n  var start = System.currentTimeMillis();\u0026#xD;\n  while(i\u0026lt;100000) { i=i+1;m.put(i,i);};\u0026#xD;\n  var end = System.currentTimeMillis();\u0026#xD;\n  println(end-start);\u0026#xD;\n  println(m.size)\u0026#xD;\n28\u0026#xD;\nscala\u0026gt;\u0026#xD;\n  val m = new java.util.concurrent.ConcurrentHashMap[Int,Int]; \u0026#xD;\n  var i = 0;\u0026#xD;\n  var start = System.currentTimeMillis();\u0026#xD;\n  while(i\u0026lt;100000) { i=i+1;m.put(i,i);};\u0026#xD;\n  var end = System.currentTimeMillis();\u0026#xD;\n  println(end-start);\u0026#xD;\n  println(m.size)\u0026#xD;\n55\u0026#xD;\n

\u0026#xD;\n

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

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

\u0026#xD;\n

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

Yammer从Scala转向Java相关推荐

  1. Yammer 从 Scala 转向 Java 使用技巧及问题

    转自:http://www.scalachina.com/portal.php?mod=view&aid=374 近日,由Yammer雇员Coda Hale发给Typesafe的Scala商业 ...

  2. Scala与Java交互

    2019独角兽企业重金招聘Python工程师标准>>> ###代码示例 假如我们想要根据某个特定国家(比如法国)的习惯来获取并格式化当前日期, 我们可以使用以下 Scala 和 Ja ...

  3. Scala调用Java静态成员及静态方法注意点——只能通过当前类名调用而不能借助子类调用父类静态成员/方法

    只能通过当前类名NioUtil调用静态成员 package com.zxl.scalaimport cn.hutool.core.io.{FileUtil, IoUtil, NioUtil} impo ...

  4. 详解Scala与Java的互动

    详解Scala与Java的互动

  5. scala调用java代码_scala调用java代码

    scala调用java代码 @(SCALA)[scala] 在scala中调用java代替非常非常简单,直接调用即可 (一)一个简单示例 1.创建一个java类 package com.lujinho ...

  6. Scala与Java集合互转摘要

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  7. 如何获取Kafka的消费者详情——从Scala到Java的切换

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  8. scala调用java代码

    scala调用java代码 @(SCALA)[scala] 详细代码请见https://github.com/lujinhong/scalademo 在scala中调用java代替非常非常简单,直接调 ...

  9. Scala入门到精通——第二十八节 Scala与JAVA互操作

    本节主要内容 JAVA中调用Scala类 Scala中调用JAVA类 Scala类型参数与JAVA泛型互操作 Scala与Java间的异常处理互操作 1. JAVA中调用Scala类 Java可以直接 ...

最新文章

  1. 2-7-PatchesAdministration
  2. 如何在 20 分钟内给你的 K8s PaaS 上线一个新功能?
  3. php 计划任务 不执行,CentOS 系统下 Laravel 计划任务 PHP artisan schedule:run 不执行,应该如何处理?...
  4. 数独基本规则_思维训练|数独入门第五课:唯余解法
  5. mysql可以用except吗_MYSQL 支持EXCEPT语句吗? 例子里EXCEPT后面的换成NOT IN可以吗? 两个例子错在哪里啊?...
  6. 项目开发中如何写说明文档
  7. 互联网晚报 | 8月22日 星期日 | 抖音回应腾讯《扫黑风暴》相关投诉;比亚迪半导体被中止上市审核;三星正式推出UPC技术...
  8. MySQL数据库如何启动?
  9. python十六进制转pcap文件_python处理pcap文件——数据提取
  10. Visual Studio + VAssistX常用快捷键
  11. 1 进 2 出 HDMI 1.4 分配器,带 HDCP 引擎、抖动清除和信号中继
  12. vue幸运大转盘实现
  13. 详细解说Windows 8.1与Windows 8的区别(Win8.1与Win8区别)
  14. unity 字符串 小技巧
  15. Halium 9 尝鲜 -- 在小米平板4上的移植 (二)
  16. scm概念的scm存储
  17. visio第一次作业
  18. 嵌入式 | 飞思卡尔MC9S12XEP100芯片CAN波特率配置
  19. 2023-05-30-数据结构课程设计
  20. 项目总结四:神经风格迁移项目(Art generation with Neural Style Transfer)

热门文章

  1. 自己写的 根据编码搜索文件的小工具
  2. antisamy java_antisamy的使用方法
  3. android闹钟详细设计,基于LabVIEW的闹钟设计 详细文档+程序
  4. mysql重启root不能登_Mysql 5.7.28初始化使用root无法登录
  5. python编译器怎么运行不在路径中的py文件_对python当中不在本路径的py文件的引用详解...
  6. 5 拦截器拦截请求路由_手写简易版axios拦截器,实现微信小程序wx.request的封装与拦截...
  7. java在集合中的方法变动的类_java中级面试题 之基础篇
  8. 【OS】操作系统的特征与功能
  9. 波士顿大学研究生计算机科学专业排名,波士顿大学计算机科学排名2020年专家资讯深度分析...
  10. android摄像头框架,FS_S5PC100平台上Android Camera架构分析