gpt4 book ai didi

scala - 减少使用 shapeless HList 时的编译时间

转载 作者:行者123 更新时间:2023-12-04 22:54:31 25 4
gpt4 key购买 nike

斯卡拉 2.12.6,无形 2.3.3。

我有很多非常深的大型模型(案例类)。我使用 shapeless 来帮助使用/操作这些模型,并且还使用像 circe 这样大量使用 shapeless 的库。

这导致我的编译时间在 phase typer 期间大量增加。 scalac 的一部分。

基于一些谷歌搜索,看起来无形是罪魁祸首,但我似乎无法找到任何关于如何改进这一点的具体提示。

有人建议,因为我为相同的模型多次解析 HList 隐式(因为有多个库),所以我应该“缓存它们” - 但是我不确定如何确切地确定要缓存的内容。

给出类似的东西:

case class MyModel(value: String) extends AnyVal
case class MyOtherModel(value: Int) extends AnyVal
case class MyRootModel(myModel: MyModel, myOtherModel: MyOtherModel)

我应该缓存什么 MyModel/ MyOtherModelMyRootModel ?

最佳答案

您可以缓存 Shapeless 的 LabelledGeneric像这样的实例:

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]]
}

您当然应该看看这是否可以改善您自己项目中的编译时间,但作为快速基准,我们可以设置一个测试来解决 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
}

(请注意,我们必须拆分调用,因为如果我们在单个方法中连续转储一千个调用,当我们注释掉要比较的实例缓存时,宏生成的代码将超过 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
}
TypeOf不过,这是一些奇怪的魔法,老实说,当我需要这样的东西时,我刚刚使用了 the方法。

作为脚注,由于您特别提到了 circe,您可能想要提供 circe-derivation一试。它可以直接替代 circe-generic 的大部分功能,但不是基于 Shapeless 构建的,并且编译速度更快。

关于scala - 减少使用 shapeless HList 时的编译时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56233806/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com