2

I have a DAO object which I defined as a case class.

case class StudentDAO(id: Int) {
  def getGPA: Double = // Expensive database lookup goes here
  def getRank: Int = // Another expensive database operation and computation goes here
  def getScoreCard: File = // Expensive file lookup goes here
}

I would naturally make getGPA and getRank and getScoreCard defs and not vals because I don't want them to be computed before they may be used.

What would be the performance impact if I marked these methods as lazy vals instead of defs? The reason I want to make them lazy vals is: I do not want to recompute the rank each time for a Student with id "i".

I am hoping that this will not be marked as duplicate because there are several questions as below which are mostly about differences:

When to use val, def, and lazy val in Scala?

def or val or lazy val for grammar rules?

`def` vs `val` vs `lazy val` evaluation in Scala

Scala Lazy Val Question

This question is mainly aimed towards the expenses (tradeoffs between CPU vs. memory) in making a method a lazy val for costly operations and what would one suggest over other and why?

EDIT: Thank you for the comment @om-nom-nom. I should have been more clear with what I was looking for.

I read here:

Use of lazy val for caching string representation

that string representation of the object is cached (see @Dave Griffith's answer). More precisely I am looking at the impact of Garbage Collection if I made it a lazy val instead of def

Community
  • 1
  • 1
Sudheer Aedama
  • 2,116
  • 2
  • 21
  • 39

2 Answers2

9

Seems pretty straightforward to me:

I don't want them to be computed before they may be used. [...] I do not want to recompute the rank each time for a Student with id "i".

Then use lazy val and that's it.

def is used when the value may change for each call, typically because you pass parameters, val won't change but will be computed right away.

vptheron
  • 7,426
  • 25
  • 34
  • 1
    So it makes sense to make it `def` instead of `lazy val` because the value may change ? Then it better be a `def`! What about the impact on garbage collection ? Please see my edit. – Sudheer Aedama Jul 22 '14 at 16:52
  • 1
    If the value may change then it is definitely a `def`. A `val` will be computed once and that's it. – vptheron Jul 22 '14 at 16:55
  • Makes sense. Say if the value is not going to change and I want to use `lazy val` instead of `def`, what is the impact on GC ? – Sudheer Aedama Jul 22 '14 at 16:57
  • It would be an attribute for your instance, it would not be garbage collected until there is no more reference to your `StudentDAO`. – vptheron Jul 22 '14 at 17:14
  • 3
    If the value can be recomputed but you want to hold on to the computed value unless the GC needs memory, have a look at `WeakReference` – Mario Camou Jul 22 '14 at 19:08
3

A lazy val for an "ordinary" reference type (e.g., File) has the effect of creating a strong reference the first time it is evaluated. Thus, while it will avoid re-evaluations of an unchanging value, it has the obvious cost of keeping the computed value in memory.

For primitive values (or even lightweight objects, like File), this memory cost usually isn't much of an issue (unless you're holding lots of Student objects in memory). For a heavy reference, though (e.g., a large data structure), you might be better off using a weak reference, some other caching approach, or just computing the value on-demand.

Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108