scala是否缓存到功能接口的转换
Scala 2.12可以自动将lambda表达式转换为接口。例如,我正在使用:scala是否缓存到功能接口的转换,scala,lambda,functional-interface,single-abstract-method,Scala,Lambda,Functional Interface,Single Abstract Method,Scala 2.12可以自动将lambda表达式转换为接口。例如,我正在使用: import org.apache.kafka.common.serialization.{Deserializer,Serde,Serializer} 导入scalapb.GeneratedMessageCompanion 类ProtoSerde[A data.toByteArray override def反序列化器():反序列化器[A]=(字符串,数据:数组[Byte])=>companion.parseFro
import org.apache.kafka.common.serialization.{Deserializer,Serde,Serializer}
导入scalapb.GeneratedMessageCompanion
类ProtoSerde[A data.toByteArray
override def反序列化器():反序列化器[A]=(字符串,数据:数组[Byte])=>companion.parseFrom(数据)
}
它会自动缓存已创建对象的实例,以便不会在每次调用时分配新对象。例如,我希望:
import org.apache.kafka.common.serialization.{Deserializer,Serde,Serializer}
导入scalapb.GeneratedMessageCompanion
类ProtoSerde[A data.toByteArray
lazy val_反序列化程序:反序列化程序[A]=(字符串,数据:数组[Byte])=>companion.parseFrom(数据)
重写def序列化程序():序列化程序[A]=\U序列化程序
重写def反序列化程序():反序列化程序[A]=\U反序列化程序
}
编译器会自动执行此优化,还是我必须自己执行此优化?编译器不会执行此类优化。将lambda表达式转换为接口并不意味着将该接口的实例保存为单例或任何其他保存方式。每次调用此lambda时,它都会创建此实例。您需要自己进行此优化。
def
不会被记录为每次调用它都会重新计算值。它可能稍后由JIT编译器进行优化
但有一个更简单的解决方案可以使类的属性记忆。Scala允许在重写父方法时将def
更改为val
。还可以在扩展类时添加lazy
修饰符:
class ProtoSerde[A <: scalapb.GeneratedMessage](implicit companion: GeneratedMessageCompanion[A])
extends Serde[A] {
override lazy val serializer: Serializer[A] = (_: String, data: A) => data.toByteArray
override lazy val deserializer: Deserializer[A] = (_: String, data: Array[Byte]) => companion.parseFrom(data)
}
class ProtoSerde[A data.toByteArray
重写lazy val反序列化器:反序列化器[A]=(uxAE:字符串,数据:数组[Byte])=>companion.parseFrom(数据)
}
也许最好在您的特定环境中进行基准测试
trait Quxable[A] {
def qux(x: A): A
}
class FooImpl1 {
def zar(): Quxable[Int] = (x: Int) => x + 1
}
class FooImpl2 {
val _zar: Quxable[Int] = (x: Int) => x + 1
def zar(): Quxable[Int] = _zar
}
// sbt "jmh:run -i 5 -wi 5 -f 2 -t 1 -prof gc bench.So61983239"
@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So61983239 {
val end = 1000000
val fooImpl1 = new FooImpl1
val fooImpl2 = new FooImpl2
@Benchmark def impl1 = (1 to end) map (x => fooImpl1.zar().qux(x))
@Benchmark def impl2 = (1 to end) map (x => fooImpl2.zar().qux(x))
}
为两者提供类似的分配率(gc.alloc.rate
)
它比这更复杂。最后它是一个实现细节,但并非在所有情况下都会创建类,甚至可能会缓存。请参阅Brian Goetz的Lambda表达式翻译:
[info] Benchmark Mode Cnt Score Error Units
[info] So61983239.impl1 thrpt 10 76.866 ± 2.690 ops/s
[info] So61983239.impl1:·gc.alloc.rate thrpt 10 4790.899 ± 167.414 MB/sec
[info] So61983239.impl1:·gc.alloc.rate.norm thrpt 10 68637392.621 ± 0.152 B/op
[info] So61983239.impl1:·gc.churn.PS_Eden_Space thrpt 10 4793.715 ± 174.955 MB/sec
[info] So61983239.impl1:·gc.churn.PS_Eden_Space.norm thrpt 10 68686591.527 ± 1866568.380 B/op
[info] So61983239.impl1:·gc.churn.PS_Survivor_Space thrpt 10 6.216 ± 1.411 MB/sec
[info] So61983239.impl1:·gc.churn.PS_Survivor_Space.norm thrpt 10 89091.175 ± 20368.810 B/op
[info] So61983239.impl1:·gc.count thrpt 10 234.000 counts
[info] So61983239.impl1:·gc.time thrpt 10 1055.000 ms
[info] So61983239.impl2 thrpt 10 78.027 ± 0.889 ops/s
[info] So61983239.impl2:·gc.alloc.rate thrpt 10 4862.226 ± 54.507 MB/sec
[info] So61983239.impl2:·gc.alloc.rate.norm thrpt 10 68637392.613 ± 0.162 B/op
[info] So61983239.impl2:·gc.churn.PS_Eden_Space thrpt 10 4895.604 ± 148.716 MB/sec
[info] So61983239.impl2:·gc.churn.PS_Eden_Space.norm thrpt 10 69105653.917 ± 1668136.154 B/op
[info] So61983239.impl2:·gc.churn.PS_Survivor_Space thrpt 10 5.582 ± 2.634 MB/sec
[info] So61983239.impl2:·gc.churn.PS_Survivor_Space.norm thrpt 10 78851.978 ± 37413.327 B/op
[info] So61983239.impl2:·gc.count thrpt 10 230.000 counts
[info] So61983239.impl2:·gc.time thrpt 10 1073.000 ms