在这种情况下,为什么使用scala并行性能会降低性能?

时间:2013-02-23 10:37:48

标签: java scala

类TestClassString返回字符串的java.util.List

对象TestViewPerformance记录调用方法TestViewController.iterateList所花费的时间。

在iterateList中,当删除并行性时,运行这个小程序所需的时间始终至少快100ms:

mySeq.par 至 mySeq

我意识到有一个用于测量scala性能的基准测试工具,如下所示: http://docs.scala-lang.org/overviews/parallel-collections/performance.html

但是我仍然希望这个程序能够使用基于当前毫秒时间的并行性来更快地运行吗? .par循环中的所有代码是否都分布在多个核心上?

以下是整个代码:

package testpackage

import java.util.Calendar

object TestViewPerformance {

  def main(args:Array[String]) = {

      val before = Calendar.getInstance().getTimeInMillis()

      val testViewController = new TestViewController();
      val testClassString : TestClassString = new TestClassString()

      val folderList = testClassString.getStringList()
      var buffer = new scala.collection.mutable.ListBuffer[String]
      val seq = scala.collection.JavaConversions.asScalaBuffer(folderList);

      /*
       * this method (iterateList) is where the parallelism occurs
       */
      testViewController.iterateList(seq)

      val after = Calendar.getInstance().getTimeInMillis()

      println(before)
      println(after)
      println(after-before)

  }

  class TestViewController {

      def iterateList(mySeq : Seq[String]) = {

        for (seqVal<- mySeq) {
            if(seqVal.equalsIgnoreCase("test")){            

            }
        }   
}

}

}

package testpackage;

import java.util.ArrayList;
import java.util.List;

public class TestClassString {

    public List<String> getStringList(){

        List<String> l = new ArrayList<String>();

        for(int i = 0; i < 1000000; ++i){
            String test = ""+Math.random();
            l.add(test);
        } 

        return l;
    }

}

2 个答案:

答案 0 :(得分:7)

因为您的基准测试是测量线程切换和量子波动的开销。在循环中添加至少Thread.sleep(1),看看会发生什么:

scala> val strings = (1 to 10000).map(_ + Math.random().toString)
strings: scala.collection.immutable.IndexedSeq[String] = Vector(10.8907863042670979, 20.2871957696184603, 30.20011325237932742, 40.7490949002788928, 50.5073228980632211...
scala> val time = System.currentTimeMillis; 
       | for (str <- strings.par) {Thread.sleep(1)}; 
       | System.currentTimeMillis - time
res0: Long = 1398

scala> val time = System.currentTimeMillis; 
       | for (str <- strings) {Thread.sleep(1)}; 
       | System.currentTimeMillis - time
res3: Long = 11129

答案 1 :(得分:3)

这可能是因为每次迭代的大部分时间都花在打印到System.out上,这是一个因此无法并行化的同步操作。因此,启动线程,调度它们并使它们同步所引起的成本使得并行迭代比顺序迭代慢。