Is there any time or space overhead to case classes over regular classes in Scala?
Is there any overhead at all in using case classes in Scala versus regular classes? Does it use any extra memory, do more in construction, or do more in field access? Or is it literally just free equals/hashcode/tostring/apply/unapply/etc for classes at the bottom of the type hierarchy?
My use case is a cl开发者_StackOverflow社区ass that deserves to be a case class (immutable and equal if all fields are equal), but I'm in a domain where performance is critical.
(Please don't answer along the lines of "stop worrying about premature optimization".)
Case classes always keep all their parameters as fields. Other classes do only if their parameters are referenced by some method. That's the only performance difference I can think of, except for larger code size due to the extra methods.
If you compile a minimal example:
class Ordinary(val i: Int) { }
case class Case(i: Int) { }
you find that the bytecode for the ordinary class is smaller (~700 vs. ~3500); you also find with javap -c -private -v <Classname>
that the constructor has an extra method call to the Product trait initializer (which doesn't actually do anything, so should be optimized away by the JIT compiler).
So for repeated use of one class, it shouldn't make much difference. If you have many thousands of such classes, you might find increased bytecode problematic.
First the obvious one: the bytecode is bigger due to the extra methods created.
Case classes retain the parameters of the first parameter list as val
members. If you don't need to access a parameter other than during construction of the object this is wasteful.
Since Scala 2.8, case classes also retain the parameters from subsequent parameter sections to support the copy
method. This is an implementation detail, and is subject to change.
scala> case class A(a: Int)(b: Int)
defined class A
scala> val a = A(0)(1)
a: A = A(0)
scala> a.copy()()
res9: A = A(0)
scala> :javap -private A
Compiled from "<console>"
public class A extends java.lang.Object implements scala.ScalaObject,scala.Product,scala.Serializable{
private final int a;
private final int b;
public scala.collection.Iterator productIterator();
public scala.collection.Iterator productElements();
public int a();
public A copy(int, int);
public int copy$default$2(int);
public int copy$default$1();
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public java.lang.String productPrefix();
public int productArity();
public java.lang.Object productElement(int);
public boolean canEqual(java.lang.Object);
private final boolean gd1$1(int);
public A(int, int);
}
精彩评论