mar*_*iop 3 performance scala typeclass
我正在尝试分析在Scala中使用类型类的性能成本,因为我注意到当它们被广泛使用时,性能往往会下降.我们来看一个ByteCodec类型类:
trait ByteCodec[T] {
def put(index: Int, byteBuffer: ByteBuffer, t: T): Unit
def get(index: Int, byteBuffer: ByteBuffer): T
}
Run Code Online (Sandbox Code Playgroud)
让我们做一个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)
}
}
Run Code Online (Sandbox Code Playgroud)
如果我运行1亿次获取和放置,则类型类测试需要大约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 }")
}
Run Code Online (Sandbox Code Playgroud)
Aleksey在评论中已经提到了您的测试不准确的一个原因.
除此之外,你的类型类比较慢的主要原因与方法本身无关:它是Longs 的装箱/拆箱使它变慢.您可以使用@specialized注释专门化值类的类型类 :
trait ByteCodec[@specialized(Long) T]
Run Code Online (Sandbox Code Playgroud)
如果您查看签名ByteBuffer,则使用值类型,不涉及装箱/取消装箱:
public abstract ByteBuffer putLong(int index, long value);
public abstract long getLong(int index);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
181 次 |
| 最近记录: |