- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Function2: "our not-so-special little guy"
Sun, 2012-02-19, 21:48
Now that Erik has gotten AnyRef specialization working tolerably well, I looked at specializing Function2 on AnyRef and Boolean (knowing that was likely to be too much.) OK, that's quite a bit:
% git diff head^ --diff-filter=A --name-only |wc -l 654
654 new classfiles. Except:
% git diff head^ --diff-filter=A --name-only |egrep -v '(tupled|curried|andThen)' |wc -l 240
Only 240 of those are the ones I'm after (more like 120, but I expect to eat the interface/implclass hit.) And 414 are "unluckily positioned accident."
Those functions are not entirely unuseful, but they're sure not this kind of useful. There's a little chicken/egg here because a lot of us don't use them for performance reasons, and I guess explosively specializing them might help with that. But even in the best case that chicken is godzilla and the egg wouldn't feed a small family of lizards.
Two things to do, both of which make sense to me independently of whether we want to specialize F2 any further and independently of one another.
- @nospecialize annotation for members (no reason we can't do this that I can think of... am I missing one?) - move those methods out of the instances
I know it bothers our object-oriented purity to have tupled and curried in a separate object, but this way has been all lose: the huge specialization tax, and we weren't even able to get rid of the ones on the object because type inference doesn't work as well on the instance, as seen here.
http://stackoverflow.com/questions/2354277/function-tupled-and-placeholder-syntax
% git diff head^ --diff-filter=A --name-only |wc -l 654
654 new classfiles. Except:
% git diff head^ --diff-filter=A --name-only |egrep -v '(tupled|curried|andThen)' |wc -l 240
Only 240 of those are the ones I'm after (more like 120, but I expect to eat the interface/implclass hit.) And 414 are "unluckily positioned accident."
Those functions are not entirely unuseful, but they're sure not this kind of useful. There's a little chicken/egg here because a lot of us don't use them for performance reasons, and I guess explosively specializing them might help with that. But even in the best case that chicken is godzilla and the egg wouldn't feed a small family of lizards.
Two things to do, both of which make sense to me independently of whether we want to specialize F2 any further and independently of one another.
- @nospecialize annotation for members (no reason we can't do this that I can think of... am I missing one?) - move those methods out of the instances
I know it bothers our object-oriented purity to have tupled and curried in a separate object, but this way has been all lose: the huge specialization tax, and we weren't even able to get rid of the ones on the object because type inference doesn't work as well on the instance, as seen here.
http://stackoverflow.com/questions/2354277/function-tupled-and-placeholder-syntax
Sun, 2012-02-19, 22:21
#2
Re: Function2: "our not-so-special little guy"
On Sun, Feb 19, 2012 at 12:58 PM, martin odersky <martin.odersky@epfl.ch> wrote:
100+. We need to better control the effects of specialization. In
particular, do something about tupled and curried. Moving to an
implicit decorator or @nospecialize seem both valid options.
Okay, while we're on the subject here's another I just opened.
-- pasted from SI-5507 --
Can we avoid generating "V" specializations in parameter positions? I acknowledge this may be necessary for reasons which my grasp of the possibilities does not make me aware of. However, consider the substantial impact this small sounding change has.
final class Foo[@specialized T1, @specialized T2, @specialized R](f: (T1, T2) => R) { }
Right now that generates 10*10*10 = 1000 extra classfiles. If it skipped Unit for T1 and T2, which are completely useless because Unit erases to BoxedUnit and T1 and T2 are already specialized on AnyRef, then it would generate 9*9*10 = 810 classfiles, a 19% reduction. Or flipped around, we're eating an almost 25% size gain for nothing.
One can of course enumerate the types (or make one of my fancy new groups in the Specializable companion) but the point of the ticket is that it would be even better if we didn't have to tell the compiler that we don't need 25% more custom code to handle all the incoming Units we intend on processing.
Sun, 2012-02-19, 22:31
#3
Re: Function2: "our not-so-special little guy"
On Sun, Feb 19, 2012 at 10:18 PM, Paul Phillips wrote:
>
> On Sun, Feb 19, 2012 at 12:58 PM, martin odersky
> wrote:
>>
>> 100+. We need to better control the effects of specialization. In
>> particular, do something about tupled and curried. Moving to an
>> implicit decorator or @nospecialize seem both valid options.
>
>
> Okay, while we're on the subject here's another I just opened.
>
Mon, 2012-02-20, 07:51
#4
Re: Function2: "our not-so-special little guy"
On Sun, Feb 19, 2012 at 09:58:18PM +0100, martin odersky wrote:
> 100+. We need to better control the effects of specialization. In
> particular, do something about tupled and curried. Moving to an
> implicit decorator or @nospecialize seem both valid options.
It might also be good to have the reverse of @nospecialize, i.e. a way
to force specialization on methods whose type signatures don't
immediately suggest specialization.
Here's an example:
import scala.{specialized => spec}
class Foo[@spec A](a1:A, a2:A) {
def isEqual:Boolean = a1 == a2
class Bar[@spec B](b:B) {
def allEqual = a1 == b && a2 == b
}
}
Here, "isEqual" isn't specialized because the method's arguments and
return type don't mention A. "Bar" is only specialized on B currently,
but even if the class was also specialized on A its "allEqual" method
likely would not be.
Users who write code like this probably expect specialization to copy
*all* methods, and are surprised to find out that they are not, but
that adding an unused parameter of type A to a method *will* cause
scalac to create a specialized overload of that method.
An explicit annotation would probably be easier to reason about in the
long run (assuming a larger refactor along the lines of my previous
proposal [1] isn't taken).
100+. We need to better control the effects of specialization. In
particular, do something about tupled and curried. Moving to an
implicit decorator or @nospecialize seem both valid options.
Martin
On Sun, Feb 19, 2012 at 9:48 PM, Paul Phillips wrote:
> Now that Erik has gotten AnyRef specialization working tolerably well, I
> looked at specializing Function2 on AnyRef and Boolean (knowing that was
> likely to be too much.) OK, that's quite a bit:
>
> % git diff head^ --diff-filter=A --name-only |wc -l
> 654
>
> 654 new classfiles. Except:
>
> % git diff head^ --diff-filter=A --name-only |egrep -v
> '(tupled|curried|andThen)' |wc -l
> 240
>
> Only 240 of those are the ones I'm after (more like 120, but I expect to eat
> the interface/implclass hit.) And 414 are "unluckily positioned accident."
>
> Those functions are not entirely unuseful, but they're sure not this kind of
> useful. There's a little chicken/egg here because a lot of us don't use
> them for performance reasons, and I guess explosively specializing them
> might help with that. But even in the best case that chicken is godzilla
> and the egg wouldn't feed a small family of lizards.
>
> Two things to do, both of which make sense to me independently of whether we
> want to specialize F2 any further and independently of one another.
>
> - @nospecialize annotation for members (no reason we can't do this that I
> can think of... am I missing one?)
> - move those methods out of the instances
>
> I know it bothers our object-oriented purity to have tupled and curried in a
> separate object, but this way has been all lose: the huge specialization
> tax, and we weren't even able to get rid of the ones on the object because
> type inference doesn't work as well on the instance, as seen here.
>
> http://stackoverflow.com/questions/2354277/function-tupled-and-placeholder-syntax
>