【发布时间】:2019-01-07 20:26:18
【问题描述】:
我尝试搜索 stackoverflow 并且有许多相关主题,包括
val-mutable versus var-immutable in Scala
What is the difference between a var and val definition in Scala?
但我还是想澄清一下我的理解是否正确。
看起来规则正在遵循
更喜欢不可变的 val 而不是不可变的 var 而不是可变的 val 而不是可变的 变种。尤其是不可变 var 优于可变 val!
但不可变 var 的性能比可变 val 差得多,根据 REPL 中的简单测试
scala -J-Xmx2g
scala> import scala.collection.mutable.{Map => MMap}
import scala.collection.mutable.{Map=>MMap}
scala>
scala> def time[R](block: => R): R = {
| val t0 = System.nanoTime()
| val result = block // call-by-name
| val t1 = System.nanoTime()
| println("Elapsed time: " + (t1 - t0) + "ns")
| result
| }
time: [R](block: => R)R
scala>time {val mut_val = MMap[Int, Int](); for (i <- 1 to 1000000) mut_val += (i -> i)}
Elapsed time: 551073900ns
scala>time {var mut_var = MMap[Int, Int](); for (i <- 1 to 1000000) mut_var += (i -> i)}
Elapsed time: 574174400ns
scala>time {var imut_var = Map[Int, Int](); for (i <- 1 to 1000000) imut_var += (i -> i)}
Elapsed time: 860938800ns
scala>time {val mut_val = MMap[Int, Int](); for (i <- 1 to 2000000) mut_val += (i -> i)}
Elapsed time: 1103283000ns
scala>time {var mut_var = MMap[Int, Int](); for (i <- 1 to 2000000) mut_var += (i -> i)}
Elapsed time: 1166532600ns
scala>time {var imut_var = Map[Int, Int](); for (i <- 1 to 2000000) imut_var += (i -> i)}
Elapsed time: 2926954500ns
我还添加了 mutable var,即使很难,它也没有多大意义。 它的性能与 mutable val 非常相似,只是为了完成图片。 但是不可变 var 的性能要差得多。
因此,不可变 var 与可变 val 的代价是性能下降(以及更广泛的内存使用!)。有人可以再次解释支付这个价格的意义是什么吗?具体例子表示赞赏。
谢谢
【问题讨论】:
-
您永远不会将单个元素一个接一个地添加到这样的不可变映射中。你宁愿做
(1 to 2000000).view.map(i => i -> i).toMap之类的事情,应该会更快。 -
不可变性的优点在整个互联网上都有描述。您具体询问的是您所做的研究?
-
好的,您测试了使用可变地图迭代构建 2M 元素地图会更快。这是预期的。但是你不能概括这个结果,即在任何地方使用可变结构更快更简单。
-
@Carcigenicate,我虽然问题很清楚。例如, mut val 和 imut var 都不是“参照透明的”。没有一个是线程安全的。等等。预期的答案是 imut var 可能更好的具体原因 - 就像在 kag0 的答案中解释的那样。
-
@DrYWit 你的问题很清楚,但是问不变性的好处是什么是一个过于模糊的问题,正如我所提到的,已经通过一些研究回答了这个问题。如果您需要根据先前的研究对某个特定点进行澄清,这将是一个很好的问题。
标签: scala performance immutability