2

处理一个使用 circe、enumeratum 和 shapeless 等库的 scala 项目

我们定义了一些枚举,即 Region;EntityType 和 EntityAction 例如

sealed trait EntityAction extends EnumEntry with Hyphencase

case object EntityAction extends Enum[EntityAction] with CirceEnum[EntityAction] {
  //noinspection ScalaStyle
  case object * extends EntityAction

  case object CreateUser extends EntityAction
  ... omitted ...
}

我们还有一个权限模型定义为

case class Permission(
                   resource: EntityType,
                   regions: Set[Region],
                   actions: Set[EntityAction],
                   instances: Set[String]
                 )

我们还有一个 UserEntityModel(以 json 格式保存在我们的数据存储中)和一个作为 http 响应的一部分返回的 UserModel

case class UserEntityV1(
                     override val entityKey: EntityKey,
                     firstName: String,
                     lastName: String,
                     override val email: String,
                     override val permissions: Set[Permission],
                     override val revokedPermissions: Set[Permission],
                     override val status: EntityStatus
                     ...

           ) extends UserEntity

EntityKey 包含 Region 枚举,省略的字段是非枚举类型

case class User(
             override val uuid: Option[String] = None,
             firstName: String,
             lastName: String,
             email: String,
             status: EntityStatus,
             permissions: Set[Permission],
             revokedPermissions: Set[Permission]
             ...
           ) extends HasPayload

如果没有来自 UserEntity 和 User 模型的权限和 revokedPermissions,clean compile时间不到 3 分钟。包含这些字段后,编译器会遇到

java.lang.OutOfMemoryError: GC overhead limit exceeded
    at java.util.Arrays.copyOfRange(Arrays.java:3664)
    at java.lang.String.<init>(String.java:201)
    at java.lang.StringBuilder.toString(StringBuilder.java:407)
    at scala.tools.nsc.transform.Erasure.fullNameInSig$1(Erasure.scala:261)
    at scala.tools.nsc.transform.Erasure.classSig$1(Erasure.scala:292)
    at scala.tools.nsc.transform.Erasure.jsig$1(Erasure.scala:336)
    at scala.tools.nsc.transform.Erasure.boxedSig$1(Erasure.scala:243)
    at scala.tools.nsc.transform.Erasure.argSig$1(Erasure.scala:281)
    at scala.tools.nsc.transform.Erasure.$anonfun$javaSig$8(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.classSig$1(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.jsig$1(Erasure.scala:336)
    at scala.tools.nsc.transform.Erasure.boxedSig$1(Erasure.scala:243)
    at scala.tools.nsc.transform.Erasure.argSig$1(Erasure.scala:281)
    at scala.tools.nsc.transform.Erasure.$anonfun$javaSig$8(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.classSig$1(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.jsig$1(Erasure.scala:336)
    at scala.tools.nsc.transform.Erasure.boxedSig$1(Erasure.scala:243)
    at scala.tools.nsc.transform.Erasure.argSig$1(Erasure.scala:281)
    at scala.tools.nsc.transform.Erasure.$anonfun$javaSig$8(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.classSig$1(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.jsig$1(Erasure.scala:336)
    at scala.tools.nsc.transform.Erasure.boxedSig$1(Erasure.scala:243)
    at scala.tools.nsc.transform.Erasure.argSig$1(Erasure.scala:281)
    at scala.tools.nsc.transform.Erasure.$anonfun$javaSig$8(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.classSig$1(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.jsig$1(Erasure.scala:336)
    at scala.tools.nsc.transform.Erasure.boxedSig$1(Erasure.scala:243)
    at scala.tools.nsc.transform.Erasure.argSig$1(Erasure.scala:281)
    at scala.tools.nsc.transform.Erasure.$anonfun$javaSig$8(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.classSig$1(Erasure.scala:295)
    at scala.tools.nsc.transform.Erasure.jsig$1(Erasure.scala:336)
    at scala.tools.nsc.transform.Erasure.jsig$1(Erasure.scala:359)

我们通过定义一个 .sbtopts 来解决它,并使用它的一些变体,因为它代表当前的 .sbtopts 是

-J-Xms1024M
-J-Xmx4G
-J-XX:ReservedCodeCacheSize=256M
-J-XX:MaxMetaspaceSize=1024M
-J-Xss2M

玩弄 diff Xss 值以及指定 -mem ,似乎并没有造成太大的差异。

但是,包含这些字段后,clean compile平均时间现在几乎是 7 分钟(因为在一些地方使用了用户实体)

所有迹象都指向宏编译。我们正在使用自动推导。有没有办法保持样板免费并保持枚举的类型安全但减少编译时间。

当前版本是

scala version =  2.12.1
sbt version = 0.13.13 
circeVersion = "0.7.0"
enumeratumVersion = "1.5.10"
enumeratumCirceVersion = "1.5.10"
shapelessVersion = "2.3.2"

在更新到最新版本的库和 scala 2.12.3 时,编译时间跳到近 20 分钟

尝试按照调试慢编译时间的一些步骤进行操作

据我所知,它是打字机阶段

4

0 回答 0