isEmpty中Option的实施很简单 - 这是一个草图:
abstract class Option[+A] { def isEmpty:Boolean }
object None extends Option[Nothing] { def isEmpty=true }
final class Some extends Option[+A] { def isEmpty=false }
isEmpty被极度使用,包括Option本身,所以它的性能很重要,即使它是如此微不足道。
我怀疑实施它会更快:
abstract class Option[+A] { final def isEmpty = this eq None }
此实现不应该要求取消引用该选项或调用其上的任何方法,AFAIK - 只是一个简单的参考比较。
我对此进行了性能测试,但是JVM微基准测试非常棘手,我对创建有意义的结果的能力毫无信心。
我有什么因素可以忽略吗?
答案 0 :(得分:4)
(基于Eugenes Zhulenev的评论)
似乎HotSpot编译器会自动执行此优化,因为Option
只有两个子类:
Polymorphism Performance Mysteries Explained:
根据Cliff Click,服务器HotSpot编译器将双态作为多态性的一个特例来处理:"服务器编译器只能证明两个类到达一个调用站点,它将插入一个类型-check然后静态调用两个目标(然后可以进一步内联等)。"
答案 1 :(得分:4)
实际上,可能是正确的。使用以下代码:
sealed abstract class Opshun[+A] {
final def isEmpty = this eq Nun
def get: A
}
object Nun extends Opshun[Nothing] { def get = ??? }
case class Summ[+A](get: A) extends Opshun[A] {}
关于最简单的测试用例(Option
或Opshun
的数组),如果您只是测试isEmpty
,那么您建议的模式是5倍(!)更快,而您如果您使用.isEmpty
手动替换eq None
或选择None
模式匹配,则可以验证这一点。
如果你转向一个更复杂的情况,你不测试 - isEmpty
然后得到一个存储值,那么差异就不那么令人印象深刻了(快三分之一)。
所以这个建议有价值;它值得在更官方的环境中进行测试。
注意在编辑中添加:这是使用足够大的数组,以便不是所有内容都适合L2缓存。当它适合L2时,两种方式都同样快。