如何以聚合方式对 Scala 地图功能进行计时?

How to time scala map functions in an aggregative fashion?

我很难想出一个解决方案来为 Scala 映射操作中的各个函数计时。假设我的代码中有以下行:

 val foo = data.map(d => func1(d).func2())

其中 dataN 个元素的序列。我将如何计算我的程序总共执行 func1func2 的时间?由于是map操作,这些函数会被调用N次,所以每次记录都要加到一个累计时间记录中。

如何在不破坏 Scala 语法的情况下执行此操作?

注意:我想以 totalTime_inFunc1totalTime_inFunc2 结束。

看看Closure。您将声明您的函数并使它们引用作用域中的变量,然后将它们传递给映射,并使它们从作用域中递增变量。

编辑

带闭包的代码

object closure {

  var time1 = 0L
  var time2 = 0L

  def time[R](block: => R)(time: Int): R = {
    val t0 = System.nanoTime()
    val result = block    // call-by-name
    val t1 = System.nanoTime()
    if (time==1)
    time1 += t1-t0
    else
    time2 += t1-t0
    result
  }

  def fun1(i: Int): Int = {
    time{i+1}(1)
  }

  def fun2(i: Int): Int = {
    time{i+2}(2)
  }

}

val data = List(1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7)

val foo = data.map(d => closure.fun2(closure.fun1(d)))

closure.time1 // res4: Long = 22976
closure.time2 // res5: Long = 25438

编辑 2

object closure {

  var time1 = 0L
  var time2 = 0L

  def time[R](block: => R)(time: Int): R = {
    val t0 = System.nanoTime()
    val result = block    // call-by-name
    val t1 = System.nanoTime()
    if (time==1)
    time1 += t1-t0
    else
    time2 += t1-t0
    result
  }

  val data = List(1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7)

  val test = new test;

  val foo = data.map(d => {
    val fun1 = time{test.fun1(d)}(1)
    time{fun1.fun2(d)}(2)
  })

}
val s = Seq(1, 2, 3)

val (mappedSeq, totalTime) = s.map(x => {
  // call your map methods here and time
  // x is the mapped element
  val timing = 5.5
  // then return the tuple with mapped element and time taken for the map function
  (x, timing)
}).foldLeft((Seq.empty[Int], 0d))((accumulator, pair) => (accumulator._1 :+ pair._1, accumulator._2 + pair._2))

println(totalTime)
println(mappedSeq.mkString(", "))

比方说,func2() returns YourType。然后,你需要从 map 中的函数 return 元组 (YourType, Long, Long),其中第二个元组元素是 func1 的执行时间,第三个元素是 func2 的执行时间。之后,您可以使用 sum:

轻松地从元组序列中获取执行时间
val fooWithTime = {
  data.map(d => {
    def now = System.currentTimeMillis
    val beforeFunc1 = now
    val func1Result = func1(d)
    val func1Time = now - beforeFunc1
    val beforeFun2 = now
    val result = func1Result.func2()
    (result, func1Time, now - beforeFun2)
  }
}
val foo = fooWithTime.map(_._1)
val totalTimeFunc1 = fooWithTime.map(_._2).sum
val totalTimeFunc2 = fooWithTime.map(_._3).sum

此外,您可以轻松地使用您喜欢的计算执行时间的方法而不是 System.currentTimeMillis()