Scala 2.12.6,无形2.3.3
我有很多很深的大型模型(案例类)。我使用shapeless来帮助使用/操纵这些模型,还使用诸如circe之类的库,这些库大量使用了shapeless。
这导致我的编译时间在phase typerscalac 期间大大增加。
基于一点谷歌搜索,看起来无形是罪魁祸首,但是我似乎找不到任何有关如何改进它的具体技巧。
有人建议,因为我要为同一模型多次解析HList隐式(由于有多个库),所以我应该“缓存”它们-但是我不确定如何确切地找出要缓存的内容。
给出类似的东西:
case class MyModel(value: String) extends AnyVal
case class MyOtherModel(value: Int) extends AnyVal
case class MyRootModel(myModel: MyModel, myOtherModel: MyOtherModel)
Run Code Online (Sandbox Code Playgroud)
我应该为MyModel/ MyOtherModel和缓存什么MyRootModel?
您可以LabelledGeneric像这样缓存Shapeless的实例:
import shapeless.{LabelledGeneric, the}
case class MyModel(value: String) extends AnyVal
case class MyOtherModel(value: Int) extends AnyVal
case class MyRootModel(myModel: MyModel, myOtherModel: MyOtherModel)
object MyModel {
implicit val generic = the[LabelledGeneric[MyModel]]
}
object MyOtherModel {
implicit val generic = the[LabelledGeneric[MyOtherModel]]
}
object MyRootModel {
implicit val generic = the[LabelledGeneric[MyRootModel]]
}
Run Code Online (Sandbox Code Playgroud)
您当然应该看看这是否会缩短您自己项目中的编译时间,但是作为快速的基准测试,我们可以设置一个测试来解决LabelledGeneric重复的问题(在这种情况下为一千次):
object Test {
def foo0 = {
LabelledGeneric[MyRootModel]
LabelledGeneric[MyRootModel]
// repeat 98 more times...
}
def foo1 = {
LabelledGeneric[MyRootModel]
LabelledGeneric[MyRootModel]
// repeat 98 more times...
}
// and so on through foo9
}
Run Code Online (Sandbox Code Playgroud)
(请注意,我们必须对调用进行拆分,因为如果仅在单个方法中连续转储一千个调用,则在注释掉要比较的实例缓存时,宏生成的代码将超过JVM的方法大小限制。)
在我的机器上,Test.scala包含Test,案例类定义和缓存实例的文件将在3秒钟左右编译完毕。如果我们注释掉这些generic定义,则将花费12秒钟以上。这当然是不科学的,但令人鼓舞。
请注意,通常来说,implicit没有类型注释的定义不是一个好主意,您可以通过编写以下代码来避免对缓存的实例执行此操作:
import shapeless.{LabelledGeneric, TypeOf, cachedImplicit}
case class MyModel(value: String) extends AnyVal
case class MyOtherModel(value: Int) extends AnyVal
case class MyRootModel(myModel: MyModel, myOtherModel: MyOtherModel)
object MyModel {
implicit val generic: TypeOf.`LabelledGeneric[MyModel]`.type = cachedImplicit
}
object MyOtherModel {
implicit val generic: TypeOf.`LabelledGeneric[MyOtherModel]`.type = cachedImplicit
}
object MyRootModel {
implicit val generic: TypeOf.`LabelledGeneric[MyRootModel]`.type = cachedImplicit
}
Run Code Online (Sandbox Code Playgroud)
TypeOf但是,这是一些奇怪的魔术,老实说,当我需要类似这样的东西时,我只是使用了这种the方法。
作为一个脚注,由于您特别提到了circe,因此您可能想尝试一下circe派生。它可以代替circe-generic的大部分功能,但它不是基于Shapeless构建的,编译速度更快。
| 归档时间: |
|
| 查看次数: |
234 次 |
| 最近记录: |