Thoughts about RichObjects, Implicit convertions and performance

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 | Next >

Thoughts about RichObjects, Implicit convertions and performance

by Vladimir Kirichenko-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

One of the typical uses of implicit conversions is to declare
"additional" methods for the existing class. Compiler substitutes
reference to object with invocation of implicit function that typically
instantiates some kind of RichObject or anonymous object with additional
functions. For example

var i = 5;
i = i max 6;
i = i max 7;

will be compiled to 2 instantiations of RichInt. The use of anonymous
declaration in implicit will cause big performance degradation.

Also in these cases usually impossible to reuse created instance.

The idea is to create some kind of "implicit traits" for this kind of
situations that would not cause performance issues and also eliminates
the need of implicit def declarations:

implicit[Int] trait RichInt {
        def max(x: Int) = this > x
        def min(x: Int) = this < x
}

and the

i = i max 6;

will actually be compiled to "static" method invocation

i = RichInt.max(i, 6);

The performance difference is significant

object XT {

implicit def int2x(i: Int) = new {
    def sum(x: Int) = i + x
}

def sum(i:Int, x:Int) = i + x;

def main(args : Array[String]) = {

    //simple
    val iterations = 10000000
    var start = System.currentTimeMillis

    var i=0;
    var x=0;

    while(i < iterations) {
        x = x sum i sum i;
        i = i + 1;
    }

    println(x + " in " + (System.currentTimeMillis - start) );

    //fast
    start = System.currentTimeMillis

    i=0;
    x=0;

    while(i < iterations) {
        x = sum(sum(x, i),i);
        i = i + 1;
    }

    println(x + " in " + (System.currentTimeMillis - start) );

}
}
=============
266447232 in 7557
266447232 in 20



--
Best Regards,
Vladimir Kirichenko



signature.asc (262 bytes) Download Attachment

Re: Thoughts about RichObjects, Implicit convertions and performance

by Johannes Rudolph-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Structural subtyping (your new {} in int2x) uses reflection for
invocations. That's your first performance problem. Use a trait like
this:

trait SummingInt{
def sum(x:Int):Int
}
implicit def int2x(i: Int) = new SummingInt{
   def sum(x: Int) = i + x
}

And performances will be much better:
266447232 in 324
266447232 in 23
266447232 in 241
266447232 in 13
266447232 in 245
266447232 in 15
266447232 in 239
266447232 in 15
266447232 in 251
266447232 in 17
266447232 in 229
266447232 in 15
266447232 in 235
266447232 in 15
266447232 in 228
266447232 in 15
266447232 in 233
266447232 in 15
266447232 in 222
266447232 in 15

In the end performance is still 10 times worse. Your example stresses
the cost of boxing primitives. It wouldn't be as bad if you would do
the same with objects (relative to the actual calculation done). If
you want to get the best performance you will have to optimize tight
loops anyway, so you would probably refrain from using implicits in
this case.

Johannes

-----------------------------------------------
Johannes Rudolph
http://virtual-void.net



On Tue, Mar 24, 2009 at 5:23 AM, Vladimir Kirichenko
<vladimir.kirichenko@...> wrote:

> object XT {
>
> implicit def int2x(i: Int) = new {
>    def sum(x: Int) = i + x
> }
>
> def sum(i:Int, x:Int) = i + x;
>
> def main(args : Array[String]) = {
>
>    //simple
>    val iterations = 10000000
>    var start = System.currentTimeMillis
>
>    var i=0;
>    var x=0;
>
>    while(i < iterations) {
>        x = x sum i sum i;
>        i = i + 1;
>    }
>
>    println(x + " in " + (System.currentTimeMillis - start) );
>
>    //fast
>    start = System.currentTimeMillis
>
>    i=0;
>    x=0;
>
>    while(i < iterations) {
>        x = sum(sum(x, i),i);
>        i = i + 1;
>    }
>
>    println(x + " in " + (System.currentTimeMillis - start) );
>
> }
> }

Re: Thoughts about RichObjects, Implicit convertions and performance

by David Hall-15 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Mar 23, 2009 at 9:23 PM, Vladimir Kirichenko
<vladimir.kirichenko@...> wrote:

> One of the typical uses of implicit conversions is to declare
> "additional" methods for the existing class. Compiler substitutes
> reference to object with invocation of implicit function that typically
> instantiates some kind of RichObject or anonymous object with additional
> functions. For example
>
> var i = 5;
> i = i max 6;
> i = i max 7;
>
> will be compiled to 2 instantiations of RichInt. The use of anonymous
> declaration in implicit will cause big performance degradation.
>
> Also in these cases usually impossible to reuse created instance.
>
> The idea is to create some kind of "implicit traits" for this kind of
> situations that would not cause performance issues and also eliminates
> the need of implicit def declarations:
>
> implicit[Int] trait RichInt {
>        def max(x: Int) = this > x
>        def min(x: Int) = this < x
> }
>
> and the
>
> i = i max 6;
>
> will actually be compiled to "static" method invocation
>
> i = RichInt.max(i, 6);


A similar idea has been proposed along these lines before (albeit with
a different syntax), and I think it would be great to have something
like this. Someone--you? :-)--should spearhead a SIP for it.

First observation: I personally would prefer the syntax

implicit class RichInt(i: Int) {
  def max(o: Int) = if (i >= o) i else o
}

with the same semantics you propose, but that's mainly because I feel
icky about "this" pointing to something other than, well, "this".

Second observation, your benchmarking (below) is the "wrong" way to
benchmark JVM code because of the peculiarities of hotspot. You should
wrap these calls in a method and call it at least 10,000 times in a
method before clocking speeds. HotSpot can do amazing things when you
give it a chance.

That said, my understanding* is that HotSpot does not (yet**) do a
great job removing object creations, which is what is needed to really
make implicits faster.

-- David

* which could be wrong.
** see http://blog.juma.me.uk/2008/12/17/objects-with-no-allocation-overhead/

>
> The performance difference is significant
>
> object XT {
>
> implicit def int2x(i: Int) = new {
>    def sum(x: Int) = i + x
> }
>
> def sum(i:Int, x:Int) = i + x;
>
> def main(args : Array[String]) = {
>
>    //simple
>    val iterations = 10000000
>    var start = System.currentTimeMillis
>
>    var i=0;
>    var x=0;
>
>    while(i < iterations) {
>        x = x sum i sum i;
>        i = i + 1;
>    }
>
>    println(x + " in " + (System.currentTimeMillis - start) );
>
>    //fast
>    start = System.currentTimeMillis
>
>    i=0;
>    x=0;
>
>    while(i < iterations) {
>        x = sum(sum(x, i),i);
>        i = i + 1;
>    }
>
>    println(x + " in " + (System.currentTimeMillis - start) );
>
> }
> }
> =============
> 266447232 in 7557
> 266447232 in 20
>
>
>
> --
> Best Regards,
> Vladimir Kirichenko
>
>

Re: Thoughts about RichObjects, Implicit convertions and performance

by Johannes Rudolph-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Mar 24, 2009 at 7:23 AM, David Hall <dlwh@...> wrote:
> Second observation, your benchmarking (below) is the "wrong" way to
> benchmark JVM code because of the peculiarities of hotspot. You should
> wrap these calls in a method and call it at least 10,000 times in a
> method before clocking speeds. HotSpot can do amazing things when you
> give it a chance.
>
> That said, my understanding* is that HotSpot does not (yet**) do a
> great job removing object creations, which is what is needed to really
> make implicits faster.

Right, see
http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks
for some tips how to fix microbenchmarks with the Hotspot compiler of
the OpenJDK. You can use -XX:+PrintCompilation VM option (with OpenJDK
or Sun JVM) to see when methods get JIT-compiled. In this particular
case my tries showed, that the method is compiled just after (while?)
the first run, so doing 10 iterations of the whole method should
suffice.

Johannes

-----------------------------------------------
Johannes Rudolph
http://virtual-void.net

Re: Thoughts about RichObjects, Implicit convertions and performance

by Viktor Klang :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I'd like:

object MyImplicits
{
//Syntax
//      implicit[targetType] def methodName[type params](params) : returnType = { expr }


//i.e
         implicit[String] def isAllDigits = this.matches("^\\d+$")

         implicit[Z <: AnyRef] def asInstanceOf[T](implicit clasz : Manifest[T]) : clasz.cast(this)
}

//usage:

import MyImplicits._

"0000".isAllDigits

5.asInstanceOf[Fajita] //Yes, this example is the very definition of WTF

On Tue, Mar 24, 2009 at 7:42 AM, Johannes Rudolph <johannes.rudolph@...> wrote:
On Tue, Mar 24, 2009 at 7:23 AM, David Hall <dlwh@...> wrote:
> Second observation, your benchmarking (below) is the "wrong" way to
> benchmark JVM code because of the peculiarities of hotspot. You should
> wrap these calls in a method and call it at least 10,000 times in a
> method before clocking speeds. HotSpot can do amazing things when you
> give it a chance.
>
> That said, my understanding* is that HotSpot does not (yet**) do a
> great job removing object creations, which is what is needed to really
> make implicits faster.

Right, see
http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks
for some tips how to fix microbenchmarks with the Hotspot compiler of
the OpenJDK. You can use -XX:+PrintCompilation VM option (with OpenJDK
or Sun JVM) to see when methods get JIT-compiled. In this particular
case my tries showed, that the method is compiled just after (while?)
the first run, so doing 10 iterations of the whole method should
suffice.

Johannes

-----------------------------------------------
Johannes Rudolph
http://virtual-void.net



--
Viktor Klang
Senior Systems Analyst

Re: Thoughts about RichObjects, Implicit convertions and performance

by Landei :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Vladimir Kirichenko-2 wrote:
One of the typical uses of implicit conversions is to declare
"additional" methods for the existing class. Compiler substitutes
reference to object with invocation of implicit function that typically
instantiates some kind of RichObject or anonymous object with additional
functions. For example

var i = 5;
i = i max 6;
i = i max 7;

will be compiled to 2 instantiations of RichInt. The use of anonymous
declaration in implicit will cause big performance degradation.

Also in these cases usually impossible to reuse created instance.

The idea is to create some kind of "implicit traits" for this kind of
situations that would not cause performance issues and also eliminates
the need of implicit def declarations:

implicit[Int] trait RichInt {
        def max(x: Int) = this > x
        def min(x: Int) = this < x
}

and the

i = i max 6;

will actually be compiled to "static" method invocation

i = RichInt.max(i, 6);
...
IMHO it would make more sense to allow an "inversion" of the first element of a parameterlist in order to preserve performance, like in the Nice language:
[code]
//pseudocode
inversion def max(x:Int, y:Int) = if (x > y) x else y

val m = 10.max(20)
//or using the infix notation
val m = 10 max 20
[/code]

Re: Thoughts about RichObjects, Implicit convertions and performance

by Viktor Klang :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Tue, Mar 24, 2009 at 9:36 AM, Viktor Klang <viktor.klang@...> wrote:
I'd like:

object MyImplicits
{
//Syntax
//      implicit[targetType] def methodName[type params](params) : returnType = { expr }


//i.e
         implicit[String] def isAllDigits = this.matches("^\\d+$")

         implicit[Z <: AnyRef] def asInstanceOf[T](implicit clasz : Manifest[T]) : clasz.cast(this)

implicit[Z <: AnyVal] def asInstanceOf[T](implicit clasz : Manifest[T]) : clasz.cast(this)
 

}

//usage:

import MyImplicits._

"0000".isAllDigits

5.asInstanceOf[Fajita] //Yes, this example is the very definition of WTF


On Tue, Mar 24, 2009 at 7:42 AM, Johannes Rudolph <johannes.rudolph@...> wrote:
On Tue, Mar 24, 2009 at 7:23 AM, David Hall <dlwh@...> wrote:
> Second observation, your benchmarking (below) is the "wrong" way to
> benchmark JVM code because of the peculiarities of hotspot. You should
> wrap these calls in a method and call it at least 10,000 times in a
> method before clocking speeds. HotSpot can do amazing things when you
> give it a chance.
>
> That said, my understanding* is that HotSpot does not (yet**) do a
> great job removing object creations, which is what is needed to really
> make implicits faster.

Right, see
http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks
for some tips how to fix microbenchmarks with the Hotspot compiler of
the OpenJDK. You can use -XX:+PrintCompilation VM option (with OpenJDK
or Sun JVM) to see when methods get JIT-compiled. In this particular
case my tries showed, that the method is compiled just after (while?)
the first run, so doing 10 iterations of the whole method should
suffice.

Johannes

-----------------------------------------------
Johannes Rudolph
http://virtual-void.net



--
Viktor Klang
Senior Systems Analyst



--
Viktor Klang
Senior Systems Analyst

Re: Thoughts about RichObjects, Implicit convertions and performance

by Jesper Nordenberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

If this language addition is to be considered I would very much prefer a
C# extension method syntax:

def newStringMethod(this str : String)(arg1 : T1, arg2 : T2) = ...

Note the use of the "this" keyword on the first parameter.

/Jesper Nordenberg

Viktor Klang wrote:

>
>
> On Tue, Mar 24, 2009 at 9:36 AM, Viktor Klang <viktor.klang@...
> <mailto:viktor.klang@...>> wrote:
>
>     I'd like:
>
>     object MyImplicits
>     {
>     //Syntax
>     //      implicit[targetType] def methodName[type params](params) :
>     returnType = { expr }
>
>
>     //i.e
>              implicit[String] def isAllDigits = this.matches("^\\d+$")
>
>              implicit[Z <: AnyRef] def asInstanceOf[T](implicit clasz :
>     Manifest[T]) : clasz.cast(this)
>
>
> implicit[Z <: Any*Val*] def asInstanceOf[T](implicit clasz :
> Manifest[T]) : clasz.cast(this)
>  
>
>
>     }
>
>     //usage:
>
>     import MyImplicits._
>
>     "0000".isAllDigits
>
>     5.asInstanceOf[Fajita] //Yes, this example is the very definition of WTF
>
>
>     On Tue, Mar 24, 2009 at 7:42 AM, Johannes Rudolph
>     <johannes.rudolph@...
>     <mailto:johannes.rudolph@...>> wrote:
>
>         On Tue, Mar 24, 2009 at 7:23 AM, David Hall
>         <dlwh@... <mailto:dlwh@...>> wrote:
>          > Second observation, your benchmarking (below) is the "wrong"
>         way to
>          > benchmark JVM code because of the peculiarities of hotspot.
>         You should
>          > wrap these calls in a method and call it at least 10,000
>         times in a
>          > method before clocking speeds. HotSpot can do amazing things
>         when you
>          > give it a chance.
>          >
>          > That said, my understanding* is that HotSpot does not (yet**)
>         do a
>          > great job removing object creations, which is what is needed
>         to really
>          > make implicits faster.
>
>         Right, see
>         http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks
>         for some tips how to fix microbenchmarks with the Hotspot
>         compiler of
>         the OpenJDK. You can use -XX:+PrintCompilation VM option (with
>         OpenJDK
>         or Sun JVM) to see when methods get JIT-compiled. In this particular
>         case my tries showed, that the method is compiled just after
>         (while?)
>         the first run, so doing 10 iterations of the whole method should
>         suffice.
>
>         Johannes
>
>         -----------------------------------------------
>         Johannes Rudolph
>         http://virtual-void.net
>
>
>
>
>     --
>     Viktor Klang
>     Senior Systems Analyst
>
>
>
>
> --
> Viktor Klang
> Senior Systems Analyst


Re: Re: Thoughts about RichObjects, Implicit convertions and performance

by Ricky Clarkson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

How about keeping the syntax we have but in those limited cases making
it equivalent in bytecode to C#'s extension methods?

2009/3/24 Jesper Nordenberg <megagurka@...>:

> If this language addition is to be considered I would very much prefer a C#
> extension method syntax:
>
> def newStringMethod(this str : String)(arg1 : T1, arg2 : T2) = ...
>
> Note the use of the "this" keyword on the first parameter.
>
> /Jesper Nordenberg
>
> Viktor Klang wrote:
>>
>>
>> On Tue, Mar 24, 2009 at 9:36 AM, Viktor Klang <viktor.klang@...
>> <mailto:viktor.klang@...>> wrote:
>>
>>    I'd like:
>>
>>    object MyImplicits
>>    {
>>    //Syntax
>>    //      implicit[targetType] def methodName[type params](params) :
>>    returnType = { expr }
>>
>>
>>    //i.e
>>             implicit[String] def isAllDigits = this.matches("^\\d+$")
>>
>>             implicit[Z <: AnyRef] def asInstanceOf[T](implicit clasz :
>>    Manifest[T]) : clasz.cast(this)
>>
>>
>> implicit[Z <: Any*Val*] def asInstanceOf[T](implicit clasz : Manifest[T])
>> : clasz.cast(this)
>>
>>
>>    }
>>
>>    //usage:
>>
>>    import MyImplicits._
>>
>>    "0000".isAllDigits
>>
>>    5.asInstanceOf[Fajita] //Yes, this example is the very definition of
>> WTF
>>
>>
>>    On Tue, Mar 24, 2009 at 7:42 AM, Johannes Rudolph
>>    <johannes.rudolph@...
>>    <mailto:johannes.rudolph@...>> wrote:
>>
>>        On Tue, Mar 24, 2009 at 7:23 AM, David Hall
>>        <dlwh@... <mailto:dlwh@...>> wrote:
>>         > Second observation, your benchmarking (below) is the "wrong"
>>        way to
>>         > benchmark JVM code because of the peculiarities of hotspot.
>>        You should
>>         > wrap these calls in a method and call it at least 10,000
>>        times in a
>>         > method before clocking speeds. HotSpot can do amazing things
>>        when you
>>         > give it a chance.
>>         >
>>         > That said, my understanding* is that HotSpot does not (yet**)
>>        do a
>>         > great job removing object creations, which is what is needed
>>        to really
>>         > make implicits faster.
>>
>>        Right, see
>>        http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks
>>        for some tips how to fix microbenchmarks with the Hotspot
>>        compiler of
>>        the OpenJDK. You can use -XX:+PrintCompilation VM option (with
>>        OpenJDK
>>        or Sun JVM) to see when methods get JIT-compiled. In this
>> particular
>>        case my tries showed, that the method is compiled just after
>>        (while?)
>>        the first run, so doing 10 iterations of the whole method should
>>        suffice.
>>
>>        Johannes
>>
>>        -----------------------------------------------
>>        Johannes Rudolph
>>        http://virtual-void.net
>>
>>
>>
>>
>>    --    Viktor Klang
>>    Senior Systems Analyst
>>
>>
>>
>>
>> --
>> Viktor Klang
>> Senior Systems Analyst
>
>

Re: Thoughts about RichObjects, Implicit convertions and performance

by Ismael Juma :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

David Hall <dlwh <at> cs.stanford.edu> writes:
> That said, my understanding* is that HotSpot does not (yet**) do a
> great job removing object creations, which is what is needed to really
> make implicits faster.

Certainly not by default, but as it was shown in that blog entry it does well
(but not yet great) once you enable Escape Analysis in the right JDK version.
The good news is that JDK 6 Update 14 (currently available as an early access
release) is one of these.

Also, from the discussion in the comments, one can imagine that the performance
gap between no allocation and allocation that is optimised away may go away in
the future. Furthermore, in many real-world scenarios I would guess that there's
no difference as it is (not all code can benefit from aggressive loop unrolling
as the benchmark in the blog entry does).

Best,
Ismael


Re: Re: Thoughts about RichObjects, Implicit convertions and performance

by Viktor Klang :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Tue, Mar 24, 2009 at 10:15 AM, Jesper Nordenberg <megagurka@...> wrote:
If this language addition is to be considered I would very much prefer a C# extension method syntax:

def newStringMethod(this str : String)(arg1 : T1, arg2 : T2) = ...

Why not keep it simple:

implicit def newStringMethod(this : String)(args) = ...


"this" is valid as parameter name if, and only if it's the only parameter in the first parameter clause of an implicit method.
Then the compiler can mangle "this" into "implicit_this" as to not accidentally collide with anything.

It can be expanded to the equivalent Java code:

<scope> static <returnType> <methodname>(<thistype> implicit_this, <params>)
   <body>
 


Note the use of the "this" keyword on the first parameter.

/Jesper Nordenberg

Viktor Klang wrote:


On Tue, Mar 24, 2009 at 9:36 AM, Viktor Klang <viktor.klang@... <mailto:viktor.klang@...>> wrote:

   I'd like:

   object MyImplicits
   {
   //Syntax
   //      implicit[targetType] def methodName[type params](params) :
   returnType = { expr }


   //i.e
            implicit[String] def isAllDigits = this.matches("^\\d+$")

            implicit[Z <: AnyRef] def asInstanceOf[T](implicit clasz :
   Manifest[T]) : clasz.cast(this)


implicit[Z <: Any*Val*] def asInstanceOf[T](implicit clasz : Manifest[T]) : clasz.cast(this)

 

   }

   //usage:

   import MyImplicits._

   "0000".isAllDigits

   5.asInstanceOf[Fajita] //Yes, this example is the very definition of WTF


   On Tue, Mar 24, 2009 at 7:42 AM, Johannes Rudolph
   <johannes.rudolph@...
   <mailto:johannes.rudolph@...>> wrote:

       On Tue, Mar 24, 2009 at 7:23 AM, David Hall
       <dlwh@... <mailto:dlwh@...>> wrote:
        > Second observation, your benchmarking (below) is the "wrong"
       way to
        > benchmark JVM code because of the peculiarities of hotspot.
       You should
        > wrap these calls in a method and call it at least 10,000
       times in a
        > method before clocking speeds. HotSpot can do amazing things
       when you
        > give it a chance.
        >
        > That said, my understanding* is that HotSpot does not (yet**)
       do a
        > great job removing object creations, which is what is needed
       to really
        > make implicits faster.

       Right, see
       http://wikis.sun.com/display/HotSpotInternals/MicroBenchmarks
       for some tips how to fix microbenchmarks with the Hotspot
       compiler of
       the OpenJDK. You can use -XX:+PrintCompilation VM option (with
       OpenJDK
       or Sun JVM) to see when methods get JIT-compiled. In this particular
       case my tries showed, that the method is compiled just after
       (while?)
       the first run, so doing 10 iterations of the whole method should
       suffice.

       Johannes

       -----------------------------------------------
       Johannes Rudolph
       http://virtual-void.net




   --    Viktor Klang
   Senior Systems Analyst




--
Viktor Klang
Senior Systems Analyst




--
Viktor Klang
Senior Systems Analyst

Re: Thoughts about RichObjects, Implicit convertions and performance

by Vladimir Kirichenko-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> And performances will be much better:
> 266447232 in 324
> 266447232 in 23

Yes but not so better. Here is more correct benchmark:
object XT {

implicit def int2x(i: Int) = new {
   def sum(x: Int) = i + x
}

def sum(i:Int, x:Int) = i + x;


trait SummingInt{
    def xsum(x:Int):Int
}

implicit def int2xx(i: Int) = new SummingInt {
  def xsum(x: Int) = i + x
}


def withReflect(times: Int):Long = {
   var start = System.currentTimeMillis

   var i=0;
   var x=0;

   while(i < times) {
       x = x sum i sum i sum i sum i;
       i = i + 1;
   }

  System.currentTimeMillis - start
}

def withTrait(times: Int):Long = {
   var start = System.currentTimeMillis

   var i=0;
   var x=0;

   while(i < times) {
       x = x xsum i xsum i xsum i xsum i;
       i = i + 1;
   }

  System.currentTimeMillis - start

}

def withCall(times: Int):Long = {
   val start = System.currentTimeMillis

   var i=0;
   var x=0;

   while(i < times) {
       x = sum(sum(sum(sum(x, i),i),i),i);
       i = i + 1;
   }

  System.currentTimeMillis - start;

}

def main(args : Array[String]) = {

   val iterations = 100000000

   //heating it up
   withReflect(iterations);
   withTrait(iterations);
   withCall(iterations);

   val ronce = withReflect(1);
   val rtimes = withReflect(iterations);

   val tonce = withTrait(1);
   val ttimes = withTrait(iterations);

   val conce = withCall(1);
   val ctimes = withCall(iterations);

   println("reflect: " + (rtimes - ronce))
   println("trait: " + (ttimes - tonce))
   println("call: " + (ctimes - conce))
}

=================
reflect: 102842
trait: 3884
call: 0

Difference is significant and still there.


--
Best Regards,
Vladimir Kirichenko

Re: Thoughts about RichObjects, Implicit convertions and performance

by bearfeeder :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Not to be snarky about this, but I'm pretty sure that all these benchmarks will report incorrect numbers.  HotSpot does analysis on what is done inside of loops and will remove calculations of values that are not accessed when the loop is done (this actually depends on what version of JVM you're using, what your processor is, and if you're in client or server mode.)  Further, HotSpot may do loop unrolling.

So, I'm not sure one can accurately benchmark the differences between the variations on adding 1 to a subsequently discarded Int without running into these optimizations. :-(

On Tue, Mar 24, 2009 at 7:10 AM, Vladimir Kirichenko <vladimir.kirichenko@...> wrote:
> And performances will be much better:
> 266447232 in 324
> 266447232 in 23

Yes but not so better. Here is more correct benchmark:
object XT {

implicit def int2x(i: Int) = new {
  def sum(x: Int) = i + x
}

def sum(i:Int, x:Int) = i + x;


trait SummingInt{
   def xsum(x:Int):Int
}

implicit def int2xx(i: Int) = new SummingInt {
 def xsum(x: Int) = i + x
}


def withReflect(times: Int):Long = {
  var start = System.currentTimeMillis

  var i=0;
  var x=0;

  while(i < times) {
      x = x sum i sum i sum i sum i;
      i = i + 1;
  }

 System.currentTimeMillis - start
}

def withTrait(times: Int):Long = {
  var start = System.currentTimeMillis

  var i=0;
  var x=0;

  while(i < times) {
      x = x xsum i xsum i xsum i xsum i;
      i = i + 1;
  }

 System.currentTimeMillis - start

}

def withCall(times: Int):Long = {
  val start = System.currentTimeMillis

  var i=0;
  var x=0;

  while(i < times) {
      x = sum(sum(sum(sum(x, i),i),i),i);
      i = i + 1;
  }

 System.currentTimeMillis - start;

}

def main(args : Array[String]) = {

  val iterations = 100000000

  //heating it up
  withReflect(iterations);
  withTrait(iterations);
  withCall(iterations);

  val ronce = withReflect(1);
  val rtimes = withReflect(iterations);

  val tonce = withTrait(1);
  val ttimes = withTrait(iterations);

  val conce = withCall(1);
  val ctimes = withCall(iterations);

  println("reflect: " + (rtimes - ronce))
  println("trait: " + (ttimes - tonce))
  println("call: " + (ctimes - conce))
}

=================
reflect: 102842
trait: 3884
call: 0

Difference is significant and still there.


--
Best Regards,
Vladimir Kirichenko



--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp

Re: Thoughts about RichObjects, Implicit convertions and performance

by Vladimir Kirichenko-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

oops, my bad, whole loop eliminated:). this one is better:

object XT {

implicit def int2x(i: Int) = new {
   def sum(x: Int) = i + x
}

def sum(i:Int, x:Int) = i + x;


trait SummingInt{
    def xsum(x:Int):Int
}

implicit def int2xx(i: Int) = new SummingInt {
  def xsum(x: Int) = i + x
}


def withReflect(times: Int) = {
   var start = System.currentTimeMillis

   var i=0;
   var x=0;

   while(i < times) {
       x = x sum i sum i sum i sum i;
       i = i + 1;
   }

  (System.currentTimeMillis - start, x);
}

def withTrait(times: Int) = {
   var start = System.currentTimeMillis

   var i=0;
   var x=0;

   while(i < times) {
       x = x xsum i xsum i xsum i xsum i;
       i = i + 1;
   }

  (System.currentTimeMillis - start, x);

}

def withCall(times: Int) = {
   val start = System.currentTimeMillis

   var i=0;
   var x=0;

   while(i < times) {
       x = sum(sum(sum(sum(x, i),i),i),i);
       i = i + 1;
   }

  (System.currentTimeMillis - start, x);



}

def main(args : Array[String]) = {

   //simple
   val iterations = 100000000

   //heating it up
   withReflect(iterations);
   withTrait(iterations);
   withCall(iterations);

   val ronce = withReflect(1);
   val rtimes = withReflect(iterations);

   val tonce = withTrait(1);
   val ttimes = withTrait(iterations);

   val conce = withCall(1);
   val ctimes = withCall(iterations);

   println(rtimes._2 + " reflect: " + (rtimes._1 - ronce._1))
   println(ttimes._2 + " trait: " + (ttimes._1 - tonce._1))
   println(ctimes._2 + " call: " + (ctimes._1 - conce._1))

}
}

=================
-745128448 reflect: 100911
-745128448 trait: 3835
-745128448 call: 163


--
Best Regards,
Vladimir Kirichenko

Re: Thoughts about RichObjects, Implicit convertions and performance

by Vladimir Kirichenko-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> First observation: I personally would prefer the syntax
>
> implicit class RichInt(i: Int) {
>  def max(o: Int) = if (i >= o) i else o
> }

In the class-case there supposed to be some x instanceof ThatClass.
There will not be such case. I proposed trait because it's
behavioristic extensions.

--
Best Regards,
Vladimir Kirichenko

Re: Re: Thoughts about RichObjects, Implicit convertions and performance

by Vladimir Kirichenko-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Mar 24, 2009 at 11:17 AM, Ricky Clarkson
<ricky.clarkson@...> wrote:
> How about keeping the syntax we have but in those limited cases making
> it equivalent in bytecode to C#'s extension methods?

Thats much better. S# style declaration conflict with scala "curring"
declarations.
--
Best Regards,
Vladimir Kirichenko

Re: Re: Thoughts about RichObjects, Implicit convertions and performance

by Ricky Clarkson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Please could you rephrase that, or could someone else please explain it to me?

2009/3/24 Vladimir Kirichenko <vladimir.kirichenko@...>:

> On Tue, Mar 24, 2009 at 11:17 AM, Ricky Clarkson
> <ricky.clarkson@...> wrote:
>> How about keeping the syntax we have but in those limited cases making
>> it equivalent in bytecode to C#'s extension methods?
>
> Thats much better. S# style declaration conflict with scala "curring"
> declarations.
> --
> Best Regards,
> Vladimir Kirichenko
>

Re: Re: Thoughts about RichObjects, Implicit convertions and performance

by Vladimir Kirichenko-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I meant  that C#-like extension methods:

void method(this str:Sring)(x:Int)

looks ok for C# where could be the only parameter set but in scala it
will clash with multiple parameter sets

def method(x:Int)(y:Int)(z:Int) =..


On Tue, Mar 24, 2009 at 4:52 PM, Ricky Clarkson
<ricky.clarkson@...> wrote:
> Please could you rephrase that, or could someone else please explain it to me?
--
Best Regards,
Vladimir Kirichenko

Re: Thoughts about RichObjects, Implicit convertions and performance

by Vladimir Kirichenko-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Mar 24, 2009 at 4:48 PM, Vladimir Kirichenko
<vladimir.kirichenko@...> wrote:
>> First observation: I personally would prefer the syntax
>>
>> implicit class RichInt(i: Int) {
>>  def max(o: Int) = if (i >= o) i else o
>> }
>
> In the class-case there supposed to be some x instanceof ThatClass.
> There will not be such case. I proposed trait because it's
> behavioristic extensions.

oops, wrong again:))

class X(i:Int) { def dbl = i * 2 }

implicit def i2x(i:Int) = new X(i)

def f(x:X) = x.dbl

f(10)

Class is better than trait.

--
Best Regards,
Vladimir Kirichenko

Re: Re: Thoughts about RichObjects, Implicit convertions and performance

by David Hall-15 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Mar 24, 2009 at 2:17 AM, Ricky Clarkson
<ricky.clarkson@...> wrote:
> How about keeping the syntax we have but in those limited cases making
> it equivalent in bytecode to C#'s extension methods?

The reason I would push for new syntax--and in particular my new
syntax-- is because implicits are commonly used to implement a type
class pattern as well as for extension methods. For instance:

trait Ordered[T] {
  def compare(t:T) : Int // ...
  // ...
}

implicit def orderedInt(x: Int) = new OrderedInt(x);

class OrderedInt(x: Int) extends Ordered[T] {
  def compare(t: Int) = // ...
}

(You can inline this simple example, but sometimes you can't.) Under
either Vladimir's or my syntax, you could change this to be:

implicit class OrderedInt(x: Int) extends Ordered[Int] {
  def compare(t: Int) = // ...
}

You could then imagine the compiler emitting two classes, OrderedInt
and OrderedInt$, with the latter providing static methods and the
former being the "usual" type class pattern as we have it today.

-- David
< Prev | 1 - 2 | Next >