2
votes

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

2
What are you expect to hear? lazy val will cost you 10 more bytes and 200 CPU cycles?om-nom-nom
@om-nom-nom: Not exactly. Please see my edit :)Sudheer Aedama

2 Answers

9
votes

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.

3
votes

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.