【问题标题】:Memory overhead of Case classes in scalascala中Case类的内存开销
【发布时间】:2013-12-22 12:21:29
【问题描述】:

scala 中案例类的内存开销是多少?

我已经实现了一些代码来保存具有多种类型的用于 NLP 处理的实习令牌的词典。我为每种令牌类型都有一个案例类。

例如,canonical lemma/stem token 如下:

sealed trait InternedLexAtom extends LexAtom{
    def id      : Int
}
case class Lemma(id: Int) extends InternedLexAtom

我将返回这些实习标记的文档向量,我将它们包装在案例类中的原因是能够通过implicit classes 向标记添加方法。我使用这种方式向词位添加行为的原因是因为我希望词位根据不同的上下文有不同的方法。

所以我希望答案是由于类型擦除导致的零内存开销。是这样吗?

我怀疑单个指针可能包含一些 Scala 可以做的魔术的参数:(

理由

透视事物。 JVM 在加载我的词典时使用 1.5-2gigs 的内存(词典在其内存表示中不使用案例类),而 C++ 在 500-700 mb 的内存中也是如此。如果我的代码库继续按现在的方式扩展它的内存需求,我将无法在我的笔记本电脑(内存中)上做这些事情

我将通过不同的代码结构来回避这个问题。例如,如果需要,我可以去掉向量表示中的案例类。如果我不必这样做就好了。

问题扩展。

Robin 和 Pedro 已经解决了这个用例,谢谢。在这种情况下,我缺少值类。有了这些,就没有更多的缺点了。 另外:我尽量不提 C++ 的 POD 概念。但现在我必须问:D C++ POD 只是一个具有原始值的结构。如果我想将多个值打包到值类中,我将如何实现呢?我假设这就是我想要做的?

class SuperTriple(val underlying: Tuple2[Int,Int]) extends AnyVal {
    def super: underlying._1
    def triple: underlying._2
}

我确实需要上述构造,因为SuperTriple 是我用作矢量模型符号的符号:D

原始问题仍然是“案例类的开销是多少”。

【问题讨论】:

  • 如果您没有计划使用类对其进行模式匹配,则没有理由将其标记为case one。正如您所提到的,implicit 类只有三个要求: 1. 它们必须在另一个 trait/class/object 中定义。 2. 它们的构造函数中只能采用一个非隐式参数。 3.作用域内不能有与隐式类同名的方法、成员或对象。
  • 这很好,我还不知道是否需要进行模式匹配。那么,您是否间接暗示常规课程是零开销?
  • Case classes 提供的不仅仅是模式匹配:equals、hashCode 以及在这个实例中的穷举检查。
  • 我认为您将隐式类与值类混合在一起:docs.scala-lang.org/sips/pending/value-classes.html
  • 如果您将值类对象(或类似 int 的原语)放入像 Map 或 Vector 这样的数据结构中,它仍然会被装箱。因此,与使用未装箱的整数相比,存在一些显着的开销。即使您将 InternedLexAtom 变成一个值类,一个 Map[String, InternedLexAtom] 也会有每个映射条目一个对象的开销。

标签: scala nlp type-erasure micro-optimization


【解决方案1】:

在 Scala 2.10 中,您可以使用 value classes。 (在旧版本的 Scala 中,对于一个成员的开销为零,您需要使用 未装箱的标记类型。

【讨论】:

猜你喜欢
  • 2014-10-03
  • 2011-11-16
  • 2011-02-12
  • 2020-12-13
  • 2019-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-20
相关资源
最近更新 更多