近日,由Yammer僱員Coda Hale發給Typesafe的Scala商業管理層的郵件經過YCombinator被泄漏出來並在GitHub上刊出。該郵件確認Yammer正在將其基礎設施棧從Scala遷回至Java,緣由在於Scala的複雜性與性能問題。 html
Yammer的公關Shelley Risk向InfoQ證明該郵件只表明Coda Hale的我的意見而非Yammer的官方聲明;隨後,Coda Hale又在http://codahale.com/the-rest-of-the-story/上發表了一篇文章。在該文章中,Coda澄清說這個消息是來自於Donald Fischer(Typesafe的CEO)對早前一個tweet的回覆。 java
更新:近日,Yammer已經發布了聲明,宣佈對該問題的立場,聲明證明了上述猜想。聲明還指出任何語言都會有瑕疵(不只僅是Scala),該郵件只不過是嘗試提出一些建議以改進Scala的性能與其餘問題。最後,聲明說到在構建任何高性能項目時(Scala是其產品環境)都有一些問題須要解決;該郵件旨在幫助Scala不斷改進。 git
雖然Coda並未打算公開該郵件,但他經過Gist(後來被刪除了)將其放到了GitHub上以得到其餘朋友的反饋;然而,郵件內容後來被共享出來並獲得了大範圍傳播。 程序員
回到2010年8月,Coda在Yammer Engineering博客上說他們將要轉向Scala。其目標是繼續運行在JVM(出於性能緣由)上,這個轉變的結果就是減小了約50%的代碼: github
Artie最初的原型採用Java編寫,但在一個週末的試驗中,我嘗試使用Scala 2.8從新實現一次。一天後,代碼行數減小了約一半,並添加了幾個特性。我震驚了,Java開發者很容易找,但Scala團隊卻能完成更多工做
一年事後,這個決定發生了變化: 閉包
目前在Yammer,咱們正在將基礎設施遷回至Java,同時以遺留庫的形式繼續對Scala提供支持。這個過程並非那麼急,咱們剛剛開始,但須要很長時間。本質在於使用Scala而非Java做爲咱們的默認語言所產生的摩擦和複雜性並未被足夠的生產力提高或是維護工做的減小而抵消。咱們或許還會在產品中使用Scala,但主要的開發將會使用Java。
Stephen Colebourne(近日發表了文章Is Scala the new EJB2?)對這封郵件作了點評,其要點總結以下: 工具
其中一些問題可能不過重要(好比說,一門語言越流行,那麼僱傭的開發者的經驗就會越多),其中一些是根據經驗來測試的。好比說,其中一條建議就是不要使用for循環。這能夠經過以下代碼進行測試: 性能
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
這裏使用for循環(與"until"模式,不少Scala程序員都習慣這麼用)要比對應的while循環慢不少,雖然使用while循環的可讀性差一些。一樣循環的Java實現對於for和while來講都是2ms。 學習
咱們作的另外一個測試是經過從一個包含Integer對象的數據集合中加載來看看可變map的性能(這能夠在Java與Scala中進行對比,裝箱的損耗應該差很少)。 測試
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
與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的開發者將大有裨益。