使用惰性val缓存字符串表示形式 [英] Use of lazy val for caching string representation

查看:71
本文介绍了使用惰性val缓存字符串表示形式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在JAXMag的Scala特刊中遇到以下代码:

package com.weiglewilczek.gameoflife

case class Cell(x: Int, y: Int) {
  override def toString = position
  private lazy val position = "(%s, %s)".format(x, y)
}

在上面的代码中使用lazy val是否比下面的代码提供更多的性能?

package com.weiglewilczek.gameoflife

case class Cell(x: Int, y: Int) {
  override def toString = "(%s, %s)".format(x, y)
}

还是只是不必要的优化?

解决方案

关于惰性val的一件事要注意的是,尽管它们仅被计算一次,但对它们的每次访问均受到双重检查的锁定包装的保护.这对于防止两个不同的线程同时尝试初始化具有有趣结果的值是必要的.现在,双重检查锁定非常有效(现在它实际上可以在JVM中工作),并且在大多数情况下不需要进行锁定获取,但是比简单的值访问有更多的开销.

另外(并且在某种程度上显然),通过缓存对象的字符串表示形式,您显式地权衡了CPU周期,以换取更大的内存使用量. "def"版本中的字符串可以被垃圾收集,而"lazy val"版本中的字符串则不能.

最后,与绩效问题一样,如果没有基于事实的基准测试,基于理论的假设几乎没有任何意义.如果没有概要分析,您将永远无法确定,因此不妨尝试一下并查看.

I encountered the following code in JAXMag's Scala special issue:

package com.weiglewilczek.gameoflife

case class Cell(x: Int, y: Int) {
  override def toString = position
  private lazy val position = "(%s, %s)".format(x, y)
}

Does the use of lazy val in the above code provide considerably more performance than the following code?

package com.weiglewilczek.gameoflife

case class Cell(x: Int, y: Int) {
  override def toString = "(%s, %s)".format(x, y)
}

Or is it just a case of unnecessary optimization?

解决方案

One thing to note about lazy vals is that, while they are only calculated once, every access to them is protected by a double-checked locking wrapper. This is necessary to prevent two different threads from attempting to initialize the value at the same time with hilarious results. Now double-checked locking is pretty efficient (now that it actually works in the JVM), and won't require lock acquisition in most cases, but there is more overhead than a simple value access.

Additionally (and somewhat obviously), by caching the string representation of your object, you are explicitly trading off CPU cycles for possibly large increases in memory usage. The strings in the "def" version can be garbage-collected, while those in the "lazy val" version will not be.

Finally, as is always the case with performance questions, theory-based hypotheses mean nearly nothing without fact-based benchmarking. You'll never know for sure without profiling, so might as well try it and see.

这篇关于使用惰性val缓存字符串表示形式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆