Điểm mấu chốt là bạn sẽ phải tự mình đo lường cho ứng dụng của mình . Bạn có thể nhận được các kết quả khá trực quan với JVM hiện tại. Thử thứ này đi.
file TraitAbstractPackage.scala
package traitvsabstract
trait T1 { def x: Int; def inc: Unit }
trait T2 extends T1 { def x_=(x0: Int): Unit }
trait T3 extends T2 { def inc { x = x + 1 } }
abstract class C1 { def x: Int; def inc: Unit }
abstract class C2 extends C1 { def x_=(x0: Int): Unit }
abstract class C3 extends C2 { def inc { x = x + 1 } }
file TraitVsAbstract.scala
object TraitVsAbstract {
import traitvsabstract._
class Ta extends T3 { var x: Int = 0}
class Tb extends T3 {
private[this] var y: Long = 0
def x = y.toInt
def x_=(x0: Int) { y = x0 }
}
class Tc extends T3 {
private[this] var xHidden: Int = 0
def x = xHidden
def x_=(x0: Int) { if (x0 > xHidden) xHidden = x0 }
}
class Ca extends C3 { var x: Int = 0 }
class Cb extends C3 {
private[this] var y: Long = 0
def x = y.toInt
def x_=(x0: Int) { y = x0 }
}
class Cc extends C3 {
private[this] var xHidden: Int = 0
def x = xHidden
def x_=(x0: Int) { if (x0 > xHidden) xHidden = x0 }
}
def Tbillion3(t: T3) = {
var i=0; while (i<1000000000) { t.inc; i+=1 }; t.x
}
def Tbillion1(t: T1) = {
var i=0; while (i<1000000000) { t.inc; i+=1 }; t.x
}
def Cbillion3(c: C3) = {
var i=0; while (i<1000000000) { c.inc; i+=1 }; c.x
}
def Cbillion1(c: C1) = {
var i=0; while (i<1000000000) { c.inc; i+=1 }; c.x
}
def ptime(f: => Int) {
val t0 = System.nanoTime
val ans = f.toString
val t1 = System.nanoTime
printf("Answer: %s; elapsed: %.2f seconds\n",ans,(t1-t0)*1e-9)
}
def main(args: Array[String]) {
for (i <- 1 to 3) {
println("Iteration "+i)
val t1s,t3s = List(new Ta, new Tb, new Tc)
val c1s,c3s = List(new Ca, new Cb, new Cc)
t1s.foreach(x => ptime(Tbillion1(x)))
t3s.foreach(x => ptime(Tbillion3(x)))
c1s.foreach(x => ptime(Cbillion1(x)))
c3s.foreach(x => ptime(Cbillion3(x)))
println
}
}
}
Mỗi ta nên in ra 1000000000 là câu trả lời, và thời gian thực hiện nên không (nếu JVM thực sự thông minh) hoặc miễn là phải mất thêm một tỷ con số. Nhưng ít nhất là trên hệ thống của tôi, Sun JVM tối ưu hóa ngược - chạy lặp lại nhận được chậm hơn - và các lớp trừu tượng chậm hơn so với các đặc điểm. (Bạn có thể muốn chạy với java -XX:+PrintCompilation
để cố gắng tìm ra những gì xảy ra sai; Tôi nghi ngờ zombie.)
Ngoài ra, đáng chú ý là scalac -optimise không làm gì để cải thiện vấn đề - tất cả đều liên quan đến JVM.
Ngược lại, JVM JRockit chuyển thành một hiệu suất phù hợp nhất định, nhưng lại một lần nữa, đặc điểm là các lớp bị đánh bại. Vì thời gian nhất quán, tôi sẽ báo cáo: 3.35 cho các lớp (3.62s cho câu hỏi if) so với 2.51 giây cho tất cả các đặc điểm, if-statement hoặc no.
(Tôi thấy xu hướng này nói chung là đúng: Hotspot tạo ra hiệu suất cực nhanh trong một số trường hợp, và ở những trường hợp khác (như trường hợp này) bị lẫn lộn và chậm quá nhanh, JRockit không bao giờ siêu nhanh - đừng bận tâm cố gắng để có được hiệu suất giống như C ngay cả trên nguyên thủy - nhưng nó hiếm khi sai lầm.)
Nếu bạn đang suy nghĩ nghiêm túc về loại tối ưu hóa cấp thấp đó, bạn đang sử dụng ngôn ngữ lập trình sai. – Raphael
@Raphael Nếu bạn đang sử dụng Scala trên hệ thống Android hoặc tương tự, bạn có thể cần chú ý đến tất cả những thứ mà bạn thường không nghĩ đến hai lần. – wheaties
Đây không phải là tôi đang cố gắng tối ưu hóa mọi thứ. Đó là một bài tập học tập và thỏa mãn sự tò mò của riêng tôi. Tôi đánh giá cao bình luận của bạn @Raphael mặc dù. –