6

我想知道这是否:

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是一个常量并缓存它,这样它就不会每次都重新编译?

4

1 回答 1

7

它会在运行时有所不同。第一个示例中的表达式将只计算一次。每次调用时的第二次表达Foo.foo()。这里的计算意味着将隐式添加的函数“r”(来自 scala-library)应用于字符串:

scala> ".*".r
res40: scala.util.matching.Regex = .*

这个函数实际上每次调用它时都会编译正则表达式(无缓存)。

顺便说一句,运行时正则表达式的任何幼稚缓存都容易受到OutOfMemory- 但是,我相信可以安全地实现它WeakHashMap,但是当前 Java 的Pattern实现(它是 scala 的底层Regex)实际上并没有实现它,可能是因为这样的实现可能没有对性能的可预测影响(GC 可能必须在每次运行时删除大部分缓存值)。带有驱逐的缓存更容易预测,但仍然不是那么简单(谁会为它选择超时/大小?)。谈到 scala 方式,一些智能宏可以在编译时进行优化(仅对基于“字符串常量”的正则表达式进行缓存),但默认情况下:

Scala 编译器也没有对正则表达式进行任何优化,因为正则表达式不是 Scala 语言的一部分。

因此,最好将静态“”.r 结构移出函数。

于 2014-09-26T09:10:06.527 回答