我想知道是否:
object Foo {
val regex = "some complex regex".r
def foo() {
// use regex
}
}
和此:
object Foo {
def foo() {
val regex = "some complex regex".r
// use regex
}
}
会有任何性能差异。即,scala编译器会识别"some complex regex".r
是一个常量并缓存它,以便它不会每次都重新编译吗?
答案 0 :(得分:6)
它在运行时会有所不同。第一个例子的表达式只计算一次。从第二个表达式 - 每次调用Foo.foo()
时。这里的计算意味着将隐式添加的函数“r”(来自scala-library)应用于字符串:
scala> ".*".r
res40: scala.util.matching.Regex = .*
这个函数实际上在每次调用时编译正则表达式(没有缓存)。
顺便说一下,运行时对正则表达式的任何天真缓存容易受OutOfMemory
的影响 - 但是,我相信可以使用WeakHashMap
安全地实现它,但是当前Java的Pattern
实现(这是scala的Regex
)doesn't的基础实际实现它,可能是因为这样的实现可能对性能没有可预测的影响(GC可能必须在每次运行时删除大多数缓存值)。带有驱逐的缓存更容易预测,但仍然不是那么简单(谁会为它选择超时/大小?)。谈到scala-way,一些智能宏可以在编译时进行优化(仅针对'基于字符串常量'的regexp进行缓存),但默认情况下:
Scala编译器也没有关于regexp的任何优化,因为regexp不是scala语言的一部分。
因此最好将静态“”.r结构移出函数。