Multiple overloads VS Inline casting

I have noticed in the libraries that are often methods that take
multiple
parameters and each parameter can take a number of different types. A
simple example, BigDecimal#add method has two parameters: a.add(b,n),
where
a is BigDecimal, b needs to be compatible with BigDecimal and n needs to
be
compatible with Fixnum. In other words it is possible that b and n can
be
one of [NotNull]BigDecimal/!/, [NotNull]BigInteger/!/, int, double
and
object. This leads to an implementation question.

Initially it seemed sensible to abstract out the conversion of these
types -
except perhaps the best case ([NotNull]BigDecimal/!/ and int) - into a
helper method and then have just:

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, BigDecimal/!/ b, int n) …

and

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, object b, object n) …

In the second method you convert the parameters to the correct types and
pass them back to the first method. This is basically what happens in
the
current implementation of many of the Socket library methods. This
provides
a single place of conversion, which is particularly helpful given the
BigDecimal class has lots of methods that take this form that will all
use
this conversion. It makes the code readable and doesn’t create masses
of
overloads for the class.

After thinking about this for a bit I started to wonder about
performance.
This style of method does not allow performance tricks in the DLR to
benefit
the code. If you have the type lookup inside the methods then that gets
called every single time those methods are called.

The other implementation idea then is to create method overloads for all
the
permutations of the parameter types. This leads to a massive increase
in
methods but could provide better performance at run time; It may happen
already, or it certainly could in the future, that the DLR is able to
calculate the method required from the calling code (i.e. Ruby code) and
generate IL that will call that method directly during execution.
Therefore
the type lookup only needs to happen once. This would make a huge
difference in some of the BigDecimal functionality where you may well be
doing complex calculations and expecting a reasonable level of
performance.
The trouble with this is that it is a right pain to code up and leaves
lots
of room for programmer error. Also I imagine that this will lead to
even
longer start-up times for IronRuby, which I suspect is going to be the
major
performance issue going forward, what with all the code generation and
JIT
compilation.

Any one got thoughts on this?

Pete

We are well aware of this issue and have a plan to solve it:

  1.  You define overloads for type combinations that you want to 
    

optimize. I’m going to improve class initializers to have a less
overhead. Even now though the initialization doesn’t contribute
significantly to startup time.

  1.  For the rest of the parameter type combinations whose 
    

performance is not critical you define a strongly typed overload(s) that
can accept all of them. The conversions should happen automatically in
the binder. There will be some well defined conversions + a set of
attributes to customize them. The goal is not to perform type
conversions imperatively in library code if possible. The predefined
conversions will follow Ruby conversion protocols like to_i, to_s, etc.
If a particular method doesn’t support the default conversion (Ruby
library methods are inconsistent on what conversions are used) or a
there are multiple applicable conversions to chose from, attributes
would be available to specify the right one.

Tomas

From: [email protected]
[mailto:[email protected]] On Behalf Of Peter Bacon
Darwin
Sent: Saturday, July 19, 2008 12:03 PM
To: [email protected]
Subject: [Ironruby-core] Multiple overloads VS Inline casting

I have noticed in the libraries that are often methods that take
multiple parameters and each parameter can take a number of different
types. A simple example, BigDecimal#add method has two parameters:
a.add(b,n), where a is BigDecimal, b needs to be compatible with
BigDecimal and n needs to be compatible with Fixnum. In other words it
is possible that b and n can be one of [NotNull]BigDecimal/!/,
[NotNull]BigInteger/!/, int, double and object. This leads to an
implementation question.

Initially it seemed sensible to abstract out the conversion of these
types - except perhaps the best case ([NotNull]BigDecimal/!/ and int)

  • into a helper method and then have just:
    public static BigDecimal/!/ Add(CodeContext/!/ context,
    BigDecimal/!/ self, BigDecimal/!/ b, int n) …
    and
    public static BigDecimal/!/ Add(CodeContext/!/ context,
    BigDecimal/!/ self, object b, object n) …
    In the second method you convert the parameters to the correct types and
    pass them back to the first method. This is basically what happens in
    the current implementation of many of the Socket library methods. This
    provides a single place of conversion, which is particularly helpful
    given the BigDecimal class has lots of methods that take this form that
    will all use this conversion. It makes the code readable and doesn’t
    create masses of overloads for the class.

After thinking about this for a bit I started to wonder about
performance. This style of method does not allow performance tricks in
the DLR to benefit the code. If you have the type lookup inside the
methods then that gets called every single time those methods are
called.

The other implementation idea then is to create method overloads for all
the permutations of the parameter types. This leads to a massive
increase in methods but could provide better performance at run time; It
may happen already, or it certainly could in the future, that the DLR is
able to calculate the method required from the calling code (i.e. Ruby
code) and generate IL that will call that method directly during
execution. Therefore the type lookup only needs to happen once. This
would make a huge difference in some of the BigDecimal functionality
where you may well be doing complex calculations and expecting a
reasonable level of performance. The trouble with this is that it is a
right pain to code up and leaves lots of room for programmer error.
Also I imagine that this will lead to even longer start-up times for
IronRuby, which I suspect is going to be the major performance issue
going forward, what with all the code generation and JIT compilation.

Any one got thoughts on this?

Pete

So in the example I gave, what would be the preferred set of overloads?

Obviously from (1) there would be:

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, BigDecimal/!/ b, int n) …

but what form should the “strongly typed overload” that you describe in
(2)
take?

Cheers,

Pete

From: [email protected]
[mailto:[email protected]] On Behalf Of Tomas M.
Sent: Saturday,19 July 19, 2008 20:50
To: [email protected]
Subject: Re: [Ironruby-core] Multiple overloads VS Inline casting

We are well aware of this issue and have a plan to solve it:

  1.  You define overloads for type combinations that you want to
    

optimize. I’m going to improve class initializers to have a less
overhead.
Even now though the initialization doesn’t contribute significantly to
startup time.

  1.  For the rest of the parameter type combinations whose 
    

performance is
not critical you define a strongly typed overload(s) that can accept all
of
them. The conversions should happen automatically in the binder. There
will
be some well defined conversions + a set of attributes to customize
them.
The goal is not to perform type conversions imperatively in library code
if
possible. The predefined conversions will follow Ruby conversion
protocols
like to_i, to_s, etc. If a particular method doesn’t support the default
conversion (Ruby library methods are inconsistent on what conversions
are
used) or a there are multiple applicable conversions to chose from,
attributes would be available to specify the right one.

Tomas

From: [email protected]
[mailto:[email protected]] On Behalf Of Peter Bacon
Darwin
Sent: Saturday, July 19, 2008 12:03 PM
To: [email protected]
Subject: [Ironruby-core] Multiple overloads VS Inline casting

I have noticed in the libraries that are often methods that take
multiple
parameters and each parameter can take a number of different types. A
simple example, BigDecimal#add method has two parameters: a.add(b,n),
where
a is BigDecimal, b needs to be compatible with BigDecimal and n needs to
be
compatible with Fixnum. In other words it is possible that b and n can
be
one of [NotNull]BigDecimal/!/, [NotNull]BigInteger/!/, int, double
and
object. This leads to an implementation question.

Initially it seemed sensible to abstract out the conversion of these
types -
except perhaps the best case ([NotNull]BigDecimal/!/ and int) - into a
helper method and then have just:

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, BigDecimal/!/ b, int n) …

and

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, object b, object n) …

In the second method you convert the parameters to the correct types and
pass them back to the first method. This is basically what happens in
the
current implementation of many of the Socket library methods. This
provides
a single place of conversion, which is particularly helpful given the
BigDecimal class has lots of methods that take this form that will all
use
this conversion. It makes the code readable and doesn’t create masses
of
overloads for the class.

After thinking about this for a bit I started to wonder about
performance.
This style of method does not allow performance tricks in the DLR to
benefit
the code. If you have the type lookup inside the methods then that gets
called every single time those methods are called.

The other implementation idea then is to create method overloads for all
the
permutations of the parameter types. This leads to a massive increase
in
methods but could provide better performance at run time; It may happen
already, or it certainly could in the future, that the DLR is able to
calculate the method required from the calling code (i.e. Ruby code) and
generate IL that will call that method directly during execution.
Therefore
the type lookup only needs to happen once. This would make a huge
difference in some of the BigDecimal functionality where you may well be
doing complex calculations and expecting a reasonable level of
performance.
The trouble with this is that it is a right pain to code up and leaves
lots
of room for programmer error. Also I imagine that this will lead to
even
longer start-up times for IronRuby, which I suspect is going to be the
major
performance issue going forward, what with all the code generation and
JIT
compilation.

Any one got thoughts on this?

Pete

If there is an implicit conversion from whatever types you need to
convert to BigDecimal then this single overload should be sufficient:
public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/ self, BigDecimal/!/ b, int n)

The second overload you use now
public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/ self, object b, object n)

does conversions and call the first overload, right? In future the
conversions will be described by attributes on the first overload and
the second overload won’t be necessary. It also depends how we define
implicit conversions for BigDecimal. If an arbitrary method has a
BigDecimal parameter should it be possible to pass Fixnum? If that is a
common case (maybe with some exemptions) it might be reasonable to
define an implicit conversion from Fixnum to BigDecimal. Then the single
overload would handle all cases. Otherwise you would need overloads from
all types of “b” parameter that this method can take.

Also, if you want to prevent allocation of BigDecimal for “b” parameter
when Fixnum is passed in (which might be a good optimization) you need
public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/ self, int b, int n)

overload.

Note that the implicit conversions and protocol attributes are not
supported right now. It will take some time to do so.
For now

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/ self, BigDecimal/!/ b, int n)
public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/ self, object b, object n)

overloads with manual conversions might be good enough. If you want to
optimize add overloads for int and double, unless the only thing they do
is to allocate BigDecimal and call the first one. Then it doesn’t make
sense to optimize them.

Tomas

From: [email protected]
[mailto:[email protected]] On Behalf Of Peter Bacon
Darwin
Sent: Saturday, July 19, 2008 1:26 PM
To: [email protected]
Subject: Re: [Ironruby-core] Multiple overloads VS Inline casting

So in the example I gave, what would be the preferred set of overloads?
Obviously from (1) there would be:
public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/ self, BigDecimal/!/ b, int n) …
but what form should the “strongly typed overload” that you describe in
(2) take?
Cheers,
Pete

From: [email protected]
[mailto:[email protected]] On Behalf Of Tomas M.
Sent: Saturday,19 July 19, 2008 20:50
To: [email protected]
Subject: Re: [Ironruby-core] Multiple overloads VS Inline casting

We are well aware of this issue and have a plan to solve it:

  1.  You define overloads for type combinations that you want to 
    

optimize. I’m going to improve class initializers to have a less
overhead. Even now though the initialization doesn’t contribute
significantly to startup time.

  1.  For the rest of the parameter type combinations whose 
    

performance is not critical you define a strongly typed overload(s) that
can accept all of them. The conversions should happen automatically in
the binder. There will be some well defined conversions + a set of
attributes to customize them. The goal is not to perform type
conversions imperatively in library code if possible. The predefined
conversions will follow Ruby conversion protocols like to_i, to_s, etc.
If a particular method doesn’t support the default conversion (Ruby
library methods are inconsistent on what conversions are used) or a
there are multiple applicable conversions to chose from, attributes
would be available to specify the right one.

Tomas

From: [email protected]
[mailto:[email protected]] On Behalf Of Peter Bacon
Darwin
Sent: Saturday, July 19, 2008 12:03 PM
To: [email protected]
Subject: [Ironruby-core] Multiple overloads VS Inline casting

I have noticed in the libraries that are often methods that take
multiple parameters and each parameter can take a number of different
types. A simple example, BigDecimal#add method has two parameters:
a.add(b,n), where a is BigDecimal, b needs to be compatible with
BigDecimal and n needs to be compatible with Fixnum. In other words it
is possible that b and n can be one of [NotNull]BigDecimal/!/,
[NotNull]BigInteger/!/, int, double and object. This leads to an
implementation question.

Initially it seemed sensible to abstract out the conversion of these
types - except perhaps the best case ([NotNull]BigDecimal/!/ and int)

  • into a helper method and then have just:
    public static BigDecimal/!/ Add(CodeContext/!/ context,
    BigDecimal/!/ self, BigDecimal/!/ b, int n) …
    and
    public static BigDecimal/!/ Add(CodeContext/!/ context,
    BigDecimal/!/ self, object b, object n) …
    In the second method you convert the parameters to the correct types and
    pass them back to the first method. This is basically what happens in
    the current implementation of many of the Socket library methods. This
    provides a single place of conversion, which is particularly helpful
    given the BigDecimal class has lots of methods that take this form that
    will all use this conversion. It makes the code readable and doesn’t
    create masses of overloads for the class.

After thinking about this for a bit I started to wonder about
performance. This style of method does not allow performance tricks in
the DLR to benefit the code. If you have the type lookup inside the
methods then that gets called every single time those methods are
called.

The other implementation idea then is to create method overloads for all
the permutations of the parameter types. This leads to a massive
increase in methods but could provide better performance at run time; It
may happen already, or it certainly could in the future, that the DLR is
able to calculate the method required from the calling code (i.e. Ruby
code) and generate IL that will call that method directly during
execution. Therefore the type lookup only needs to happen once. This
would make a huge difference in some of the BigDecimal functionality
where you may well be doing complex calculations and expecting a
reasonable level of performance. The trouble with this is that it is a
right pain to code up and leaves lots of room for programmer error.
Also I imagine that this will lead to even longer start-up times for
IronRuby, which I suspect is going to be the major performance issue
going forward, what with all the code generation and JIT compilation.

Any one got thoughts on this?

Pete

Thanks Tomas.

From: [email protected]
[mailto:[email protected]] On Behalf Of Tomas M.
Sent: Saturday,19 July 19, 2008 23:10
To: [email protected]
Subject: Re: [Ironruby-core] Multiple overloads VS Inline casting

If there is an implicit conversion from whatever types you need to
convert
to BigDecimal then this single overload should be sufficient:

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, BigDecimal/!/ b, int n)

The second overload you use now

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, object b, object n)

does conversions and call the first overload, right? In future the
conversions will be described by attributes on the first overload and
the
second overload won’t be necessary. It also depends how we define
implicit
conversions for BigDecimal. If an arbitrary method has a BigDecimal
parameter should it be possible to pass Fixnum? If that is a common case
(maybe with some exemptions) it might be reasonable to define an
implicit
conversion from Fixnum to BigDecimal. Then the single overload would
handle
all cases. Otherwise you would need overloads from all types of “b”
parameter that this method can take.

Also, if you want to prevent allocation of BigDecimal for “b” parameter
when
Fixnum is passed in (which might be a good optimization) you need

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, int b, int n)

overload.

Note that the implicit conversions and protocol attributes are not
supported
right now. It will take some time to do so.

For now

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, BigDecimal/!/ b, int n)

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, object b, object n)

overloads with manual conversions might be good enough. If you want to
optimize add overloads for int and double, unless the only thing they do
is
to allocate BigDecimal and call the first one. Then it doesn’t make
sense to
optimize them.

Tomas

From: [email protected]
[mailto:[email protected]] On Behalf Of Peter Bacon
Darwin
Sent: Saturday, July 19, 2008 1:26 PM
To: [email protected]
Subject: Re: [Ironruby-core] Multiple overloads VS Inline casting

So in the example I gave, what would be the preferred set of overloads?

Obviously from (1) there would be:

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, BigDecimal/!/ b, int n) …

but what form should the “strongly typed overload” that you describe in
(2)
take?

Cheers,

Pete

From: [email protected]
[mailto:[email protected]] On Behalf Of Tomas M.
Sent: Saturday,19 July 19, 2008 20:50
To: [email protected]
Subject: Re: [Ironruby-core] Multiple overloads VS Inline casting

We are well aware of this issue and have a plan to solve it:

  1.  You define overloads for type combinations that you want to
    

optimize. I’m going to improve class initializers to have a less
overhead.
Even now though the initialization doesn’t contribute significantly to
startup time.

  1.  For the rest of the parameter type combinations whose 
    

performance is
not critical you define a strongly typed overload(s) that can accept all
of
them. The conversions should happen automatically in the binder. There
will
be some well defined conversions + a set of attributes to customize
them.
The goal is not to perform type conversions imperatively in library code
if
possible. The predefined conversions will follow Ruby conversion
protocols
like to_i, to_s, etc. If a particular method doesn’t support the default
conversion (Ruby library methods are inconsistent on what conversions
are
used) or a there are multiple applicable conversions to chose from,
attributes would be available to specify the right one.

Tomas

From: [email protected]
[mailto:[email protected]] On Behalf Of Peter Bacon
Darwin
Sent: Saturday, July 19, 2008 12:03 PM
To: [email protected]
Subject: [Ironruby-core] Multiple overloads VS Inline casting

I have noticed in the libraries that are often methods that take
multiple
parameters and each parameter can take a number of different types. A
simple example, BigDecimal#add method has two parameters: a.add(b,n),
where
a is BigDecimal, b needs to be compatible with BigDecimal and n needs to
be
compatible with Fixnum. In other words it is possible that b and n can
be
one of [NotNull]BigDecimal/!/, [NotNull]BigInteger/!/, int, double
and
object. This leads to an implementation question.

Initially it seemed sensible to abstract out the conversion of these
types -
except perhaps the best case ([NotNull]BigDecimal/!/ and int) - into a
helper method and then have just:

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, BigDecimal/!/ b, int n) …

and

public static BigDecimal/!/ Add(CodeContext/!/ context,
BigDecimal/!/
self, object b, object n) …

In the second method you convert the parameters to the correct types and
pass them back to the first method. This is basically what happens in
the
current implementation of many of the Socket library methods. This
provides
a single place of conversion, which is particularly helpful given the
BigDecimal class has lots of methods that take this form that will all
use
this conversion. It makes the code readable and doesn’t create masses
of
overloads for the class.

After thinking about this for a bit I started to wonder about
performance.
This style of method does not allow performance tricks in the DLR to
benefit
the code. If you have the type lookup inside the methods then that gets
called every single time those methods are called.

The other implementation idea then is to create method overloads for all
the
permutations of the parameter types. This leads to a massive increase
in
methods but could provide better performance at run time; It may happen
already, or it certainly could in the future, that the DLR is able to
calculate the method required from the calling code (i.e. Ruby code) and
generate IL that will call that method directly during execution.
Therefore
the type lookup only needs to happen once. This would make a huge
difference in some of the BigDecimal functionality where you may well be
doing complex calculations and expecting a reasonable level of
performance.
The trouble with this is that it is a right pain to code up and leaves
lots
of room for programmer error. Also I imagine that this will lead to
even
longer start-up times for IronRuby, which I suspect is going to be the
major
performance issue going forward, what with all the code generation and
JIT
compilation.

Any one got thoughts on this?

Pete