案例类.copy()和大对象

时间:2017-08-04 14:59:48

标签: scala

假设大型对象(在我的情况下是多兆字节的附件,每天数千个)通过REST端点接收并存储在这样的案例类中:

case class Box(largeBase64Object: String, results: List[String])

现在,此案例类的实例将在多个连续步骤(链)中处理。每个链步骤可以通过调用box.copy(results = "foo" :: box.results)来改变实例(实际上,这个例子是简化的,它实际上是一个无形的HList,它存储每个步骤的结果)。

单步可能是,例如病毒扫描会将扫描程序的结果(感染/未感染Boolean)添加到results列表中。

但是,这种方法总是会创建潜在大型附件的新副本。是的,垃圾收集迟早会收集过时的副本,但我仍然害怕潜在的开销,因为我们谈论的是每天几千兆字节的附件数据。

另一个明显的方法是将附件存储在全局可变Map中,并仅在Box中存储引用。这样可以避免每步复制一次附件,但完全不可变的数据结构的漂亮属性将会消失。

处理这些情况的规范方法是什么?有没有人指出反映这种情况的基准(复制与全局存储)?

1 个答案:

答案 0 :(得分:2)

案例类引用的对象不会被复制,只有案例类本身,所有引用都将与原始对象相同(除了那些你明确改变的对象)。

我们无法查看复制方法的源代码,因为它是由编译器生成的,但是我们可以使用-Xprint:typer编译器标志来查看它生成的代码。

对于你的案例类

case class Box(largeBase64Object: String, results: List[String])

我们看到生成的方法(我正在使用scalac 2.12.3)

<synthetic> def copy(largeBase64Object: String = largeBase64Object, results: List[String] = results): Box = new Box(largeBase64Object, results);
<synthetic> def copy$default$1: String = Box.this.largeBase64Obj
<synthetic> def copy$default$2: List[String] = Box.this.results;

正如我们所看到的,copy方法只是使用它传递的对象创建case类的新实例,并且默认只是直接使用case类的字段而不进行任何类型的复制。

相关问题