IT story

이 Scala 코드를 조금만 변경해도 성능이 크게 달라지는 이유는 무엇입니까?

hot-time 2020. 12. 25. 09:30
반응형

이 Scala 코드를 조금만 변경해도 성능이 크게 달라지는 이유는 무엇입니까?


32 비트 Debian 6.0 (Squeeze) 시스템 (2.5GHz Core 2 CPU), sun-java6 6.24-1에서 실행 중이지만 Wheezy의 Scala 2.8.1 패키지를 사용하고 있습니다.

로 컴파일 된이 코드 scalac -optimise는 실행하는 데 30 초 이상 걸립니다.

object Performance {

  import scala.annotation.tailrec

  @tailrec def gcd(x:Int,y:Int):Int = {
    if (x == 0)
      y 
    else 
      gcd(y%x,x)
  }

  val p = 1009
  val q = 3643
  val t = (p-1)*(q-1)

  val es = (2 until t).filter(gcd(_,t) == 1)
  def main(args:Array[String]) {
    println(es.length)
  }
}

그러나 val es=한 줄을 아래로 이동하고 범위 내 에서 사소한 변경을 수행하면 main단 1 초 만에 실행됩니다. 이는 동일한 C ++의 성능을보고 비교할 수있을 것으로 기대했던 것과 훨씬 더 비슷합니다. 흥미롭게도 그 자리를 그대로두고 val es=자격을 부여하는 lazy것도 동일한 가속 효과를가집니다.

여기서 무슨 일이 일어나고 있습니까? 함수 범위 밖에서 계산을 수행하는 것이 왜 그렇게 느린가요?


JVM은 메서드 호출을 최적화하는 것과 동일한 수준으로 정적 이니셜 라이저 (이것이 무엇인지)를 최적화하지 않습니다. 안타깝게도 그곳에서 많은 작업을 수행하면 성능이 저하됩니다. 이것은 완벽한 예입니다. 이것은 또한 이전 Application특성이 문제가있는 것으로 간주 된 이유 중 하나 이며, Scala 2.9 DelayedInit에는 이니셜 라이저에서 나중에 호출되는 메서드로 항목을 이동하는 데 약간의 컴파일러 도움을받는 특성 이있는 이유도 있습니다.


(편집 : "생성자"를 "초기화 자"로 수정했습니다. 다소 긴 오타!)


최상위 수준 개체 블록 내부의 코드는 개체 클래스의 정적 이니셜 라이저로 변환됩니다. Java에서 동등한 것은 다음과 같습니다.

class Performance{
    static{
      //expensive calculation
    }
    public static void main(String[] args){
      //use result of expensive calculation
    }
}

HotSpot JVM은 정적 이니셜 라이저 중에 발생한 코드에 대해 최적화를 수행하지 않습니다. 이러한 코드는 한 번만 실행된다는 합리적 경험이 있습니다.

참조 URL : https://stackoverflow.com/questions/6265864/why-does-a-small-change-to-this-scala-code-make-such-a-huge-difference-to-perfor

반응형