1. 程式人生 > >scala與Java效能對比

scala與Java效能對比

http://www.cnblogs.com/superjt/archive/2012/04/22/2465348.html

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迴圈。這可以通過如下程式碼進行測試:

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的時間代價在30ms左右,而用Scala寫卻在300ms左右。然後發現Scala程式碼中有過多的for迴圈,將for迴圈改成while後,發現Scala程度花費時間大概在190ms之間。驗證了while迴圈比for迴圈的高效。現在還在分析驗證其他原因導致Scala效率低下的問題。