Есть ли время или пространство над классами по сравнению с обычными классами в Scala? - PullRequest
10 голосов
/ 05 октября 2011

Есть ли какие-либо издержки при использовании case-классов в Scala по сравнению с обычными классами? Использует ли он какую-либо дополнительную память, делает больше в строительстве или делает больше в полевом доступе? Или это буквально просто бесплатно равно / hashcode / tostring / apply / unapply / etc для классов в нижней части иерархии типов?

Мой вариант использования - это класс, который заслуживает того, чтобы быть классом случая (неизменным и равным, если все поля равны), но я нахожусь в области, где производительность критична.

(Пожалуйста, не отвечайте в духе "перестаньте беспокоиться о преждевременной оптимизации".)

Ответы [ 3 ]

17 голосов
/ 05 октября 2011

Классы Case всегда сохраняют все свои параметры в виде полей. Другие классы делают, только если их параметры ссылаются каким-либо методом. Это единственное различие в производительности, о котором я могу думать, за исключением большего размера кода из-за дополнительных методов.

7 голосов
/ 05 октября 2011

Если вы компилируете минимальный пример:

class Ordinary(val i: Int) { }

case class Case(i: Int) { }

вы обнаружите, что байт-код для обычного класса меньше (~ 700 против ~ 3500); с помощью javap -c -private -v <Classname> вы также обнаружите, что у конструктора есть дополнительный вызов метода для инициализатора свойств продукта (который на самом деле ничего не делает, поэтому должен быть оптимизирован компилятором JIT).

Так что для повторного использования одного класса это не должно иметь большого значения. Если у вас есть много тысяч таких классов, увеличение байт-кода может оказаться проблематичным.

5 голосов
/ 05 октября 2011

Сначала очевидное: байт-код больше из-за созданных дополнительных методов.

Классы Case сохраняют параметры первого списка параметров как val члены.Если вам не нужен доступ к параметру, кроме как во время создания объекта, это бесполезно.

Начиная с Scala 2.8, классы case также сохраняют параметры из последующих разделов параметров для поддержки метода copy.Это подробности реализации, и может быть изменено .

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...