스칼라와 Java 성능간에 매우 이상한 차이가 발생했습니다. Java에서 inversion counting 루틴을 구현 한 다음 모든 스칼라 스칼라 버전 (List
또는 Stream
사용)이 스택 오버플로/메모리 부족 오류로 인해 매우 느리거나 충돌하기 때문에 Scala로 줄 단위로 이식했습니다. 하지만이 버전은 느린 편 이었지만 Java 버전은 100,000 개의 정수 배열을 처리하는 데 22ms가 걸렸지 만 Scala 버전은 3 초가 걸렸습니다. 스칼라 버전의 관련 코드는 다음과 같습니다.스칼라 대 Java 성능
def mergeAndCountInversions(xs: Array[Int], aux: Array[Int], left: Int, right: Int) = {
xs.copyToArray(aux)
val m = left + (right - left)/2
var i = left
var j = m + 1
var inv: Long = 0
for (k <- left to right) {
if (i > m) {
xs(k) = aux(j)
j += 1
} else if (j > right) {
xs(k) = aux(i)
i += 1
} else if (aux(j) < aux(i)) {
xs(k) = aux(j)
j += 1
inv += (m - i) + 1
} else {
xs(k) = aux(i)
i += 1
}
}
inv
}
이 루틴의 성능을 향상시키는 방법에 대한 아이디어가 있습니까?
UPD : Scala 버전의 성능 저하는 완전히 내 잘못입니다. 첫 번째 문은 전체 배열을 보조 배열에 불필요하게 복사합니다. 필요한 부분 만 복사하도록 변경하면 Java와 성능이 비슷합니다.
이 질문에 대한 답변을 작성하기에는 스칼라가 충분하지 않지만 스칼라의 배열 인덱싱은 배열 객체에 대해 'apply' 메소드를 호출하는 것으로 간주합니다. Java에서 수행하는 포인터 연산과 똑같은 것은 아닙니다 후드는 대괄호로 배열 액세스 구문을 사용할 때! – kqr
우선 : [jmh] (http://openjdk.java.net/projects/code-tools/jmh/)를 사용하여 예열 후 성능 **을 측정하십시오. 인라인 한 후에도 동일한 성능을 얻을 것입니다. 또한 (Scalaxy) (https://github.com/ochafik/Scalaxy/tree/master/Loops)를 사용하여 컴파일 타임에 'for (k <- 왼쪽에서 오른쪽으로 최적화)'와 같이 인라이닝을 적용 할 수 있습니다. – senia
@senia 벤치 마크 루틴을 사용하여 질문을 업데이트했습니다. – synapse