Home > other >  Time taken for loop vs map flatmap combination
Time taken for loop vs map flatmap combination

Time:08-25

Iam trying to understand functional programming using scala. So the question is very basic. To start off, I have a trait which looks something like this

trait DebugLogger{
  def time(stageName:String)(func : => Unit):Unit = {
    val currentTime= System.currentTimeMillis()
    println(s"Stage ${stageName} started at ${currentTime}")
    func
    println(s"Stage ${stageName} completed.. Took ${(System.currentTimeMillis() - currentTime)/1000.0} seconds")
  }
}

Now I have a function which looks something like this

object GeneralRecap extends App with DebugLogger {
  val aCondition: Boolean = true
  val list1 = Seq(1,2,4,4)
  val list2 = Seq('a','b','c','d')
  time ("Time taken in for loop"){
    val a1 = for (i <- list1;
                  j <- list2
                  ) yield i * j
    println(a1)
  }

time("Time taken in flatmap") {
  val c = list1 flatMap (number => list2.map(value => number * value))
  println(c)
}

I was assuming the bytecode that both the functions would generate would be the same and was assuming both the functions would take the same time to process. However to my surprise this is how the output ended up with

Stage Time taken in for loop started at 1661398450618
List(97, 98, 99, 100, 194, 196, 198, 200, 388, 392, 396, 400, 388, 392, 396, 400)
Stage Time taken in for loop completed.. Took 0.011 seconds
Stage Time taken in flatmap started at 1661398450629
List(97, 98, 99, 100, 194, 196, 198, 200, 388, 392, 396, 400, 388, 392, 396, 400)
Stage Time taken in flatmap completed.. Took 0.001 seconds

So the flatmap map way takes 1/10th of the for loop time. Considering both the functions are n square, I would assume that it should have taken the same time. Any reason why the first one takes more time than the other

CodePudding user response:

There are all sorts of problems with that time method. Firstly it is including the time for the first println in the total, and secondly there may well be formatting code executed before the second time is captured.

This is a much better version:

def time(stageName: String)(func: => Unit): Unit = {
  println(s"Starting ${stageName}")

  val startTime = System.currentTimeMillis()
  func
  val endTime = System.currentTimeMillis()

  val elapsed = (endTime - startTime) / 1000.0

  println(s"Stage ${stageName} completed. Took $elapsed seconds")
}

More importantly you can't measure Scala performance on a single run. There is a lot of optimisation that happens during the run of a program that means that the first pass is usually significantly slower than the later ones.

  • Related