복붙노트

[SCALA] 어떻게 스칼라의 방법을 프로파일 링하는?

SCALA

어떻게 스칼라의 방법을 프로파일 링하는?

스칼라 메소드 호출을 프로파일 링하는 표준 방법은 무엇입니까?

내가 필요로 무엇 후크 내가 시작하고 정지 타이머에 사용할 수있는 사용 방법 주위에.

자바 I 사용 모습 프로그래밍 AspectJ를, 상기 방법은 프로파일 링되도록 정의하고 바이트 분사이를 달성했다.

전에 그 과정에서 정적 타이핑을 잃지 않고 함수 후에 호출 할 내가 기능의 무리를 정의 할 수 있습니다 스칼라에서 더 자연스러운 방법이 있나요?

해결법

  1. ==============================

    1.당신이 타이밍을 측정하고자하는 코드를 변경하지 않고이 작업을 수행 하시겠습니까? 당신이 코드를 변경 꺼리지 않는 경우에, 당신이 뭔가를 할 수 있습니다 :

    당신이 타이밍을 측정하고자하는 코드를 변경하지 않고이 작업을 수행 하시겠습니까? 당신이 코드를 변경 꺼리지 않는 경우에, 당신이 뭔가를 할 수 있습니다 :

    def time[R](block: => R): R = {
        val t0 = System.nanoTime()
        val result = block    // call-by-name
        val t1 = System.nanoTime()
        println("Elapsed time: " + (t1 - t0) + "ns")
        result
    }
    
    // Now wrap your method calls, for example change this...
    val result = 1 to 1000 sum
    
    // ... into this
    val result = time { 1 to 1000 sum }
    
  2. ==============================

    2.예스퍼의 대답 이외에, 당신은 자동으로 REPL에서 메소드 호출을 래핑 할 수 있습니다 :

    예스퍼의 대답 이외에, 당신은 자동으로 REPL에서 메소드 호출을 래핑 할 수 있습니다 :

    scala> def time[R](block: => R): R = {
       | val t0 = System.nanoTime()
       | val result = block
       | println("Elapsed time: " + (System.nanoTime - t0) + "ns")
       | result
       | }
    time: [R](block: => R)R
    

    - 지금이에서의 랩 아무것도 할 수

    scala> :wrap time
    wrap: no such command.  Type :help for help.
    

    OK - 우리는 절전 모드에있을 필요가

    scala> :power
    ** Power User mode enabled - BEEP BOOP SPIZ **
    ** :phase has been set to 'typer'.          **
    ** scala.tools.nsc._ has been imported      **
    ** global._ and definitions._ also imported **
    ** Try  :help,  vals.<tab>,  power.<tab>    **
    

    멀리 랩

    scala> :wrap time
    Set wrapper to 'time'
    
    scala> BigDecimal("1.456")
    Elapsed time: 950874ns
    Elapsed time: 870589ns
    Elapsed time: 902654ns
    Elapsed time: 898372ns
    Elapsed time: 1690250ns
    res0: scala.math.BigDecimal = 1.456
    

    5 시간이 초과 내가 아무 생각이없는 이유 인쇄 재료

    2.12.2의로 업데이트 :

    scala> :pa
    // Entering paste mode (ctrl-D to finish)
    
    package wrappers { object wrap { def apply[A](a: => A): A = { println("running...") ; a } }}
    
    // Exiting paste mode, now interpreting.
    
    
    scala> $intp.setExecutionWrapper("wrappers.wrap")
    
    scala> 42
    running...
    res2: Int = 42
    
  3. ==============================

    3.당신이 이용하실 수있는 스칼라 세 벤치마킹 라이브러리가있다.

    당신이 이용하실 수있는 스칼라 세 벤치마킹 라이브러리가있다.

    링크 된 사이트의 URL이 변경 될 수 있기 때문에, 나는 아래의 관련 콘텐츠를 붙여 넣기하고있다.

  4. ==============================

    4.이것은 내가 무엇을 사용 :

    이것은 내가 무엇을 사용 :

    import System.nanoTime
    def profile[R](code: => R, t: Long = nanoTime) = (code, nanoTime - t)
    
    // usage:
    val (result, time) = profile { 
      /* block of code to be profiled*/ 
    }
    
    val (result2, time2) = profile methodToBeProfiled(foo)
    
  5. ==============================

    5.testing.Benchmark 유용 할 수 있습니다.

    testing.Benchmark 유용 할 수 있습니다.

    scala> def testMethod {Thread.sleep(100)}
    testMethod: Unit
    
    scala> object Test extends testing.Benchmark {
         |   def run = testMethod
         | }
    defined module Test
    
    scala> Test.main(Array("5"))
    $line16.$read$$iw$$iw$Test$     100     100     100     100     100
    
  6. ==============================

    6.나는 예스퍼에서 솔루션을 가져다가 같은 코드의 여러 실행에 일부 집계를 추가

    나는 예스퍼에서 솔루션을 가져다가 같은 코드의 여러 실행에 일부 집계를 추가

    def time[R](block: => R) = {
        def print_result(s: String, ns: Long) = {
          val formatter = java.text.NumberFormat.getIntegerInstance
          println("%-16s".format(s) + formatter.format(ns) + " ns")
        }
    
        var t0 = System.nanoTime()
        var result = block    // call-by-name
        var t1 = System.nanoTime()
    
        print_result("First Run", (t1 - t0))
    
        var lst = for (i <- 1 to 10) yield {
          t0 = System.nanoTime()
          result = block    // call-by-name
          t1 = System.nanoTime()
          print_result("Run #" + i, (t1 - t0))
          (t1 - t0).toLong
        }
    
        print_result("Max", lst.max)
        print_result("Min", lst.min)
        print_result("Avg", (lst.sum / lst.length))
    }
    

    이 두 가지 기능 counter_new 및 counter_old 시간에 원하는 가정, 다음은 사용법은 다음과 같습니다

    scala> time {counter_new(lst)}
    First Run       2,963,261,456 ns
    Run #1          1,486,928,576 ns
    Run #2          1,321,499,030 ns
    Run #3          1,461,277,950 ns
    Run #4          1,299,298,316 ns
    Run #5          1,459,163,587 ns
    Run #6          1,318,305,378 ns
    Run #7          1,473,063,405 ns
    Run #8          1,482,330,042 ns
    Run #9          1,318,320,459 ns
    Run #10         1,453,722,468 ns
    Max             1,486,928,576 ns
    Min             1,299,298,316 ns
    Avg             1,407,390,921 ns
    
    scala> time {counter_old(lst)}
    First Run       444,795,051 ns
    Run #1          1,455,528,106 ns
    Run #2          586,305,699 ns
    Run #3          2,085,802,554 ns
    Run #4          579,028,408 ns
    Run #5          582,701,806 ns
    Run #6          403,933,518 ns
    Run #7          562,429,973 ns
    Run #8          572,927,876 ns
    Run #9          570,280,691 ns
    Run #10         580,869,246 ns
    Max             2,085,802,554 ns
    Min             403,933,518 ns
    Avg             797,980,787 ns
    

    희망이 도움이됩니다

  7. ==============================

    7.나는 코드 블록에서 이동하기 쉽게 기술을 사용합니다. 요점은 그 똑같은 라인의 시작 및 종료 타이머 - 정말 간단한 복사하고 붙여 넣을 수 있도록. 다른 좋은 것은 당신이 그 같은 라인에있는 모든 문자열로 당신에게 어떤 타이밍 수단을 정의 할 수 있다는 것입니다.

    나는 코드 블록에서 이동하기 쉽게 기술을 사용합니다. 요점은 그 똑같은 라인의 시작 및 종료 타이머 - 정말 간단한 복사하고 붙여 넣을 수 있도록. 다른 좋은 것은 당신이 그 같은 라인에있는 모든 문자열로 당신에게 어떤 타이밍 수단을 정의 할 수 있다는 것입니다.

    사용 예제 :

    Timelog("timer name/description")
    //code to time
    Timelog("timer name/description")
    

    코드:

    object Timelog {
    
      val timers = scala.collection.mutable.Map.empty[String, Long]
    
      //
      // Usage: call once to start the timer, and once to stop it, using the same timer name parameter
      //
      def timer(timerName:String) = {
        if (timers contains timerName) {
          val output = s"$timerName took ${(System.nanoTime() - timers(timerName)) / 1000 / 1000} milliseconds"
          println(output) // or log, or send off to some performance db for analytics
        }
        else timers(timerName) = System.nanoTime()
      }
    

    장점 :

    단점 :

  8. ==============================

    8.@의 결 리게의 대답의 단순처럼 나는뿐만 아니라 원 :

    @의 결 리게의 대답의 단순처럼 나는뿐만 아니라 원 :

    이 여기에 달성된다 :

    def profile[R] (repeat :Int)(code: => R, t: Long = System.nanoTime) = { 
      (1 to repeat).foreach(i => code)
      (System.nanoTime - t)/repeat
    }
    

    더욱 정확도를 간단한 변형은 작은 조각을 타이밍하는 JVM 핫스팟 예열 루프 (초과하지 않음) 허용 :

    def profile[R] (repeat :Int)(code: => R) = {  
      (1 to 10000).foreach(i => code)   // warmup
      val start = System.nanoTime
      (1 to repeat).foreach(i => code)
      (System.nanoTime - start)/repeat
    }
    
  9. ==============================

    9.ScalaMeter 스칼라에서 벤치마킹을 수행하는 좋은 라이브러리입니다

    ScalaMeter 스칼라에서 벤치마킹을 수행하는 좋은 라이브러리입니다

    다음은 간단한 예제이다

    import org.scalameter._
    
    def sumSegment(i: Long, j: Long): Long = (i to j) sum
    
    val (a, b) = (1, 1000000000)
    
    val execution_time = measure { sumSegment(a, b) }
    

    당신이 스칼라 워크 시트에 코드보다 실행하면 당신은 밀리 초 단위로 실행 시간을 얻을

    execution_time: org.scalameter.Quantity[Double] = 0.260325 ms
    
  10. ==============================

    10.하지만 거인의 어깨에 서 ...

    하지만 거인의 어깨에 서 ...

    고체 타사 라이브러리는 더 이상적 일 것이다, 그러나 당신이 뭔가 빠르고 기반의 표준 라이브러리를 필요로하는 경우, 다음과 같은 변형을 제공합니다 :

    .

    import scala.concurrent.duration._
    import scala.language.{postfixOps, implicitConversions}
    
    package object profile {
    
      def profile[R](code: => R): R = profileR(1)(code)
    
      def profileR[R](repeat: Int)(code: => R): R = {
        require(repeat > 0, "Profile: at least 1 repetition required")
    
        val start = Deadline.now
    
        val result = (1 until repeat).foldLeft(code) { (_: R, _: Int) => code }
    
        val end = Deadline.now
    
        val elapsed = ((end - start) / repeat)
    
        if (repeat > 1) {
          println(s"Elapsed time: $elapsed averaged over $repeat repetitions; Total elapsed time")
    
          val totalElapsed = (end - start)
    
          println(s"Total elapsed time: $totalElapsed")
        }
        else println(s"Elapsed time: $elapsed")
    
        result
      }
    }
    

    나는 이것이 예를 들어, 실행 사이의 약간의 시간 차이가 확실하지 얼마나 친절 해요하지만 당신이 할 수있는 가장 큰 시간 단위로 변환 할 Duration.toCoarsest 방법을 사용할 수 있습니다 주목할 가치가

    Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
    Type in expressions to have them evaluated.
    Type :help for more information.
    
    scala> import scala.concurrent.duration._
    import scala.concurrent.duration._
    
    scala> import scala.language.{postfixOps, implicitConversions}
    import scala.language.{postfixOps, implicitConversions}
    
    scala> 1000.millis
    res0: scala.concurrent.duration.FiniteDuration = 1000 milliseconds
    
    scala> 1000.millis.toCoarsest
    res1: scala.concurrent.duration.Duration = 1 second
    
    scala> 1001.millis.toCoarsest
    res2: scala.concurrent.duration.Duration = 1001 milliseconds
    
    scala> 
    
  11. ==============================

    11.당신은에 System.currentTimeMillis을 사용할 수 있습니다 :

    당신은에 System.currentTimeMillis을 사용할 수 있습니다 :

    def time[R](block: => R): R = {
        val t0 = System.currentTimeMillis()
        val result = block    // call-by-name
        val t1 = System.currentTimeMillis()
        println("Elapsed time: " + (t1 - t0) + "ms")
        result
    }
    

    용법:

    time{
        //execute somethings here, like methods, or some codes.
    }  
    

    nanoTime는 NS 표시됩니다, 그래서 열심히보고 있습니다. 난 당신이 대신의 전에 currentTimeMillis를 사용하는 것이 좋습니다 그래서.

  12. from https://stackoverflow.com/questions/9160001/how-to-profile-methods-in-scala by cc-by-sa and MIT license