blue-sky
blue-sky

Reputation: 53806

Why using scala parallelism have slower performance in this case?

The class TestClassString returns a java.util.List of Strings

The object TestViewPerformance records the time taken to call method TestViewController.iterateList.

Within iterateList the time taken to run this small program is consistently at least 100ms faster when parallelism is removed :

mySeq.par to mySeq

I realise there is benchmarking tool used for measuring scala performance as specified here : http://docs.scala-lang.org/overviews/parallel-collections/performance.html

But still I would expect this program to run faster using parallelism based on current millisecond time ? Is all code within the .par loop spread over multiple cores ?

Here is the entire code :

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;
    }

}

Upvotes: 2

Views: 655

Answers (2)

Denis Tulskiy
Denis Tulskiy

Reputation: 19177

Because your benchmark is measuring overhead of thread switching and quantum fluctuations. Add at least Thread.sleep(1) to your loop and see what happens:

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

Upvotes: 8

JB Nizet
JB Nizet

Reputation: 691715

It's probably because most of the time in each iteration is spent printing to System.out, which is a synchronized operation that is thus not parallelizable. So the cost induced by starting threads, scheduling them and synchronize them makes the parallel iteration slower than the sequential one.

Upvotes: 3

Related Questions