- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Re: Avoiding boxing/unboxing with specializations and numeric
Oops! Could this please be moved to scala-user! I posted to the wrong list by accident.
Oops! Could this please be moved to scala-user! I posted to the wrong list by accident.
Copyright © 2013 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland
Re: Re: Avoiding boxing/unboxing with specializations and numer
On Thu, Dec 1, 2011 at 3:34 PM, marc <millstone [at] gmail [dot] com> wrote:
Avoiding boxing/unboxing with specializations and numeric
I thought now would be a good time to post the following: Currently, much of my codeis hardcoded to double and I wanted to generalize this to handle Double or Ints withouta performance loss.
Below is a simple example I wrote up demonstrating the problems I am experiencing(as well as javap output).
This code simply creates a class that accepts a List[T] and will compute its sum.If T is an Int, we want an Int back and similarly if T is a Double.Observations: 1) It seems we have to implicitly go through Numeric to handle this use case, requiring the useof plus and zero as opposed to + and 0.2) Although the class itself is specialized, we have to pay a boxing/unboxing penalty forthe use of the plus operator in the recursion. Obviously, this is inherently tied to havingto go though the implicit conversion to Numeric.
Obviously, this example is very simple, but I hope it is so simple that some of thesemicro-optimization techniques can be better explained.
Is this just the way it is or am I missing something with using this functionality?
Thank you all in advance,
import scala.annotation.tailrecobject Run { def main(args:Array[String]) { val A = new MList(List(1.,2.,3.)) val B = new MList(List(1,2,3)) println(A.sum) println(B.sum) }}
class MList[@specialized (Int,Double) T:Numeric](a:List[T]){ def sum(implicit num: Numeric[T]) = { import num._ @tailrec def sumHelper(a:List[T],total:T):T = { if (a.length == 0) total else sumHelper(a.tail, plus(a.head,total)) } sumHelper(a,zero) }}
javap -c -private MList\$mcI\$sp output
private final int sumHelper$3(scala.collection.immutable.List, int, scala.math.Numeric); Code: 0: aload_1 1: invokeinterface #56, 1; //InterfaceMethod scala/collection/LinearSeqOptimized.length:()I 6: iconst_0 7: if_icmpne 12 10: iload_2 11: ireturn 12: aload_1 13: invokeinterface #61, 1; //InterfaceMethod scala/collection/TraversableLike.tail:()Ljava/lang/Object; 18: checkcast #63; //class scala/collection/immutable/List 21: aload_3 22: aload_1 23: invokeinterface #68, 1; //InterfaceMethod scala/collection/IterableLike.head:()Ljava/lang/Object; 28: iload_2 29: invokestatic #50; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer; 32: invokeinterface #72, 3; //InterfaceMethod scala/math/Numeric.plus:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 37: invokestatic #38; //Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I 40: istore_2 41: astore_1 42: goto 0