2011-10-04 5 views
10

정규 클래스 대 스칼라의 사례 클래스 사용에 오버 헤드가 있습니까? 추가 메모리를 사용하거나, 건설에 더 많은 시간을 할애하거나, 현장 접근에 더 많은 시간을 할애합니까? 또는 형식 계층의 맨 아래에있는 클래스에 문자 그대로 무료 equals/hashcode/tostring/apply/unapply/etc입니까?스칼라의 일반 클래스보다 케이스 클래스에 시간이나 공간 오버 헤드가 있습니까?

유스 케이스는 사례 클래스 (모든 필드가 같으면 변경 불가능하고 동일해야 함)가되어야하는 클래스이지만 성능이 중요한 도메인에 있습니다.

+1

이 질문에 대한 답변이 아니지만 'scalac -print Whatever.scala' 컴파일러에'-print' 플래그를 사용하여 스칼라가 사례 클래스에 생성하는 메서드를 직접 볼 수 있습니다. –

답변

17

케이스 클래스는 항상 필드로 모든 매개 변수를 유지 ("조기 최적화에 대한 걱정 그만".의 라인을 따라 대답하지 마십시오). 다른 클래스는 매개 변수가 어떤 메소드에 의해 참조되는 경우에만 수행됩니다. 이는 내가 생각할 수있는 유일한 성능 차이입니다. 추가 방법으로 인해 더 큰 코드 크기는 제외됩니다.

+0

감사! 나는 'scalac -print'출력에서 "scala.Product $ class ./* Product $ class */$ init $ (Case.this);" 생성자에서. 슈퍼 컨스트럭터를 부르는 것 이상의 추가 작업이 필요한지 알고 있습니까? – phoenix

+0

생성자 (클래스 본문) 내부에서만 호출되는 매개 변수에 대한 참조가 유지됩니까? – ziggystar

5

첫 번째는 바이트 코드가 생성 된 추가 메서드로 인해 더 큽니다.

사례 클래스는 첫 번째 매개 변수 목록의 매개 변수를 val 구성원으로 유지합니다. 객체를 생성하는 동안 이외의 매개 변수에 액세스 할 필요가 없다면 이것은 낭비입니다.

스칼라 2.8부터 케이스 클래스는 copy 메서드를 지원하기 위해 후속 매개 변수 섹션의 매개 변수도 유지합니다. 이것은 구현 세부 사항이며 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); 
} 
7

당신이 최소한의 예를 컴파일 할 경우

class Ordinary(val i: Int) { } 

case class Case(i: Int) { } 

는 일반 클래스의 바이트 코드가 작은 (~ 700 대 ~ 3500)는 것을 알게을; javap -c -private -v <Classname>을 통해 생성자에 Product trait initializer (실제로 아무것도 수행하지 않으므로 JIT 컴파일러로 최적화해야 함)에 대한 추가 메서드 호출이 있음을 알 수 있습니다.

따라서 한 클래스를 반복해서 사용하면 큰 차이가 없어야합니다. 이러한 클래스가 수천 개에 이르면 바이트 코드의 증가 문제가있을 수 있습니다.

관련 문제