This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Re: Inlining of val access - Scala performance continued

No replies
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.

Yay for reply all.

On Oct 13, 2011 8:27 PM, "√iktor Ҡlang" <viktor [dot] klang [at] gmail [dot] com> wrote:

How do you suggest that a lazy val should be inlined, bytecode wise?

Also, for the val, you need to mark it as final. Also, you need to compile with -optimise, and @inline is just a hint.

On Oct 13, 2011 7:43 PM, "Edmondo Porcu" <edmondo [dot] porcu [at] gmail [dot] com> wrote:
class SimpleTestClass(val elem:Int) extends MyTrait{
  @inline lazy val out:Int=elem
  println("I am a base class " + elem);
  @inline val value=out;
}


class SimpleTestClass2(elem:Int) extends MyTrait{
  val element:MyTrait = new SimpleTestClass(10);
  println("I am a child class " + elem)
  @inline val value = element.value;
}

class SimpleTestClass3(size:Int)extends MyTrait{
  val items=List.tabulate(size)(_*2);
  @inline lazy val value = items.size
}

object TestCase {
  def main(items:String*){
    val item1:MyTrait = new SimpleTestClass2(12)
    val item2:MyTrait = new SimpleTestClass(3)
    val item3:MyTrait = new SimpleTestClass3(3)
    println(item1.value)
    println(item2.value)
    println(item3.value)
  }
}

trait MyTrait {
  def value:Int
}

When compiling with scalac -optimise -Ydebug -Ylog:inline        concreteMethod.isEffectivelyFinal: true
[log inliner] Treating CALL_METHOD scala.Predef.println (dynamic)
        receiver: module class Predef
        icodes.available: true
        concreteMethod.isEffectivelyFinal: true
[log inliner] shouldInline: com.gottex.gottware.common.datamodels.finance.collections.curves.TestCase.main with scala.Predef.println
[log inliner] shouldInline(scala.Predef.println) score: 0
[log inliner] method method println is used on a non-empty stack with finalizer.
[log inliner] shouldInline: com.gottex.gottware.common.datamodels.finance.collections.curves.TestCase.main with scala.Predef.println
[log inliner] shouldInline(scala.Predef.println) score: 0
[log inliner] inline failed for scala.Predef.println:
  pair.sameSymbols: false
  inc.numInlined < 2: true
  inc.hasCode: true
  isSafeToInline: true
  shouldInline: false

[log inliner] method method println is used on a non-empty stack with finalizer.
[log inliner]  com.gottex.gottware.common.datamodels.finance.collections.curves.TestCase.main blocks before inlining: 1 (43) after: 1 (43)
[log inliner] Analyzing com.gottex.gottware.common.datamodels.finance.collections.curves.MyTrait
[log inliner] Analyzing com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1
[log inliner] Analyzing com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply count 0 with 1 blocks
[log inliner] shouldLoadImplFor: anonymous class SimpleTestClass3$$anonfun$1.method apply$mcII$sp: false
[log inliner] Treating CALL_METHOD com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply$mcII$sp (dynamic
)
        receiver: anonymous class SimpleTestClass3$$anonfun$1
        icodes.available: true
        concreteMethod.isEffectivelyFinal: true
[log inliner] shouldInline: com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply with com.gottex.gottwar
e.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply$mcII$sp
[log inliner] shouldInline(com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply$mcII$sp) score: 1
[log inliner] method method apply$mcII$sp is used on a non-empty stack with finalizer.
[log inliner] Inlining com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply$mcII$sp in com.gottex.gottwa
re.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply at pos: 1039
[log inliner] Analyzing com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply count 0 with 3 blocks
[log inliner]  com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply blocks before inlining: 1 (4) after:
 1 (8)
[log inliner] Analyzing com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply$mcII$sp count 0 with 1 bloc
ks
[log inliner]  com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply$mcII$sp blocks before inlining: 1 (4
) after: 1 (4)
[log inliner] Analyzing com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply count 0 with 1 blocks
[log inliner] shouldLoadImplFor: anonymous class SimpleTestClass3$$anonfun$1.method apply: false
[log inliner] Treating CALL_METHOD com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply (dynamic)
        receiver: anonymous class SimpleTestClass3$$anonfun$1
        icodes.available: true
        concreteMethod.isEffectivelyFinal: true
[log inliner] method method apply is used on a non-empty stack with finalizer.
[log inliner] inline failed for com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply:
  pair.sameSymbols: false
  inc.numInlined < 2: true
  inc.hasCode: true
  isSafeToInline: true
  shouldInline: false

[log inliner] method method apply is used on a non-empty stack with finalizer.
[log inliner]  com.gottex.gottware.common.datamodels.finance.collections.curves.SimpleTestClass3$$anonfun$1.apply blocks before inlining: 1 (8) after:
 1 (8)
[running phase closelim on SimpleTestClass.scala]
[running phase dce on SimpleTestClass.scala]
[running phase jvm on icode]

It is clear for me that item1 and item2 are immutable, and such is value for both. The compiler could statically replace the values to 10 and 3 but it doesn't... and the same can be done with item3, since it's value is a lazy val.  In my benchmark, calls to lazy val inside a loop of about 10 millions iterations, ended up to account up to 10%. 

Please help me.

Best Regards
Edmondo






Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland