Ich versuche, die Kosten in der Leistung der Verwendung von typeclasses in Scala zu analysieren, weil ich festgestellt habe, dass wenn sie ausgiebig verwendet werden, die Leistung zu fallen neigen. Nehme sie zum Beispiel ein ByteCodec
typeclass:Leistung von typeclasses in Scala
trait ByteCodec[T] {
def put(index: Int, byteBuffer: ByteBuffer, t: T): Unit
def get(index: Int, byteBuffer: ByteBuffer): T
}
Lassen Sie sich dann machen Sie ein Long
Beispiel:
object ByteCodec {
def apply[T](implicit bc: ByteCodec[T]): ByteCodec[T] = bc
implicit val longBC = new ByteCodec[Long] {
@inline override def put(index: Int, byteBuffer: ByteBuffer, long: Long): Unit = {
val _ = byteBuffer.putLong(index, long)
}
@inline override def get(index: Int, byteBuffer: ByteBuffer): Long =
byteBuffer.getLong(index)
}
}
Wenn ich 100 Millionen laufen bekommt und Puts, das dauert ~ 1200ms für den typeclass Test und ~ Sonst 800ms. Wo ist der Overhead und kann ich ihn loswerden?
Der Code des Haupt:
object Main extends App {
val cycles = 100000000
val byteBuffer = ByteBuffer.allocate(java.lang.Long.BYTES)
var start = System.currentTimeMillis()
var currCycle = cycles
while (currCycle > 0) {
byteBuffer.putLong(0, 10L)
val k = byteBuffer.getLong(0)
currCycle -= 1
}
var end = System.currentTimeMillis()
println(s"time elapsed byteBuffer ${ end - start }")
val codec = ByteCodec[Long]
start = System.currentTimeMillis()
currCycle = cycles
while (currCycle > 0) {
codec.put(0, byteBuffer, 10L)
val k = codec.get(0, byteBuffer)
currCycle -= 1
}
end = System.currentTimeMillis()
println(s"time elapsed ByteCodec ${ end - start }")
}
Nehmen jmh oder sbt-jmh, und analysieren. Hier ist ein Leitfaden für eine ähnliche Frage: http://shipilev.net/blog/2014/java-scala-divided-we-fail/. Der oben erwähnte naive Benchmark fällt mindestens der Eliminierung von toten Codes in "val k = ..." und Aufwärmproblemen bei der Ausführung von Tests mit Back-to-Back-Problemen zum Opfer. –