私はScalaでのタイプキャスティングの使用のコストを分析しようとしています。私が頻繁に使用されるとパフォーマンスが低下する傾向があることに気付きました。のは、例えば、ByteCodec
型クラスを見てみましょう:Scalaでのタイプキャストのパフォーマンス
trait ByteCodec[T] {
def put(index: Int, byteBuffer: ByteBuffer, t: T): Unit
def get(index: Int, byteBuffer: ByteBuffer): T
}
だが、その後Long
インスタンスを作ってみましょう:
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)
}
}
私は100百万人を実行すると取得し、プット、これは型クラスのテストのために〜の1200msを取ると〜そうでなければ800ms。オーバーヘッドはどこにありますか?それを取り除くことはできますか?
メインのコード:すでにテストが不正確である理由のコメント一つの理由に言及した
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 }")
}
JMHを取りますまたはsbt-jmhを使用して分析します。同様の質問のためのガイドがあります:http://shipilev.net/blog/2014/java-scala-divided-we-fail/。上記の純粋なベンチマークは、少なくともval k = ...でのデッドコードの除去とテストを連続して実行するウォームアップの問題に犠牲になります。 –