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.

Re: Re: Avoiding boxing/unboxing with specializations and numer

Just forward your original message to scala-user. (You can edit the subject and body so it doesn't look forwarded, if you like.)


On Thu, Dec 1, 2011 at 3:34 PM, marc <millstone [at] gmail [dot] com> wrote:
Oops!  Could this please be moved to scala-user!  I posted to the wrong list by accident.

Avoiding boxing/unboxing with specializations and numeric

Hello all,
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

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