[Mono-list] inlining of methods using structs

Tom Larsen tomar@apricot.com
Wed, 18 Aug 2004 10:03:46 -0700 (PDT)


"Inlining" is a function of the compiler.  The runtime doesn't
particuarlly care whether the next operator is a call onto a function or
the function inline.  The tradeoff is of course the classic "speed vs
space".  A commonly used function might incur less of a performance hit if
placed in line but you've increased the IL length of every function that
is now using the code inline.

You seem to be under the guise that "structs" are lightweight.  There is
noting about ECMA CLI specification that indicates this.  In fact
"structs" can be quite complex.  The one blessing of the way C# over Java
is this seperation of "objects" (classes) and "data" (structs) but nothing
ever indicates that objects are heavier or lighter than structs.  If
anything "structs" are harder to deal with because of box/unbox.

Tom Larsen

On Wed, 18 Aug 2004, [ISO-8859-1] R=FCdiger Klaehn wrote:

> Hi,
>
> I am new on this list. I have been interested in using .NET for
> numerical problems for some time.
>
> When investigating the lower than expected performance of some code of
> mine, I found out that both the Microsoft JIT and the mono JIT do not
> inline methods with an explicit struct parameter or a struct return value=
=2E
>
> This came as quite a shock to me, since I always assumed that structs
> are the way to go for performance critical stuff. I attached an example
> for a case that would benefit tremendously from inlining of method calls
> involving structs in some way.
>
> Is there some deep philosophical reason for not inlining method calls
> involving structs? It does not make any sense for me, since especially
> in the case of small structs the opportunities for inlining and
> subsequent optimizations are huge.
>
> THis would be a nice way to improve the performance of the JIT compiler
> by a factor of 4 or so in many cases.
>
> This is the relevant code in mono/mini/mini.c:
> ---
> =09    /* fixme: why cant we inline valuetype returns? */
> =09    MONO_TYPE_ISSTRUCT (signature->ret))
> =09=09return FALSE;
>
> =09/* its not worth to inline methods with valuetype arguments?? */
> =09for (i =3D 0; i < signature->param_count; i++) {
> =09=09if (MONO_TYPE_ISSTRUCT (signature->params [i])) {
> =09=09=09return FALSE;
> =09=09}
> =09}
> ---
>
> Another thing I have noticed is that mono only inlines methods that are
> shorter than 20 bytes of IL code. I am sure that this makes sense for
> most applications, but in some cases it would be very useful to increase
> this value to 64 or maybe even 128. I think there should be a
> per-assembly attribute to specify the inlining threshold.
>
> best regards
>
> R=FCdiger
>
>
>
> This is a small benchmark for struct inlining:
> ---
> using System;
>
> namespace OperatorInliningTest
> {
>      public struct Complex
>      {
>          internal double re, im;
>          public Complex(double re, double im)
>          {
>              this.re =3D re;
>              this.im =3D im;
>          }
>          public static implicit operator Complex(double re) {
>              return new Complex(re, 0);
>          }
>          public static Complex I
>          {
>              get { return new Complex(0,1); }
>          }
>          public static Complex Zero
>          {
>              get { return new Complex(0,0); }
>          }
>          public static Complex One
>          {
>              get { return new Complex(1,0); }
>          }
>          public static Complex operator +(Complex a, Complex b)
>          {
>              return new Complex(a.re+b.re,a.im+b.im);
>          }
>          public static Complex operator *(Complex a, Complex b)
>          {
>              return new Complex(a.re*b.re-a.im*b.im,a.re*b.im+a.im*b.re);
>          }
>          public double AbsoluteSquared
>          {
>              get { return re*re+im*im; }
>          }
>      }
>      class Program
>      {
>          static int MandelbrotIteration1(Complex c)
>          {
>              Complex x =3D Complex.Zero;
>              for (int i =3D 0; i < 1000; i++)
>              {
>                  x =3D x*x+c;
>                  if (x.AbsoluteSquared > 4)
>                      return i;
>              }
>              return -1;
>          }
>          static int MandelbrotIteration4(Complex c)
>          {
>              double xre, xim, cre, cim, t;
>              xre =3D 0; xim =3D 0;
>              cre =3D c.re; cim =3D c.im;
>              for (int i =3D 0; i < 1000; i++)
>              {
>                  //x=3Dx*x...
>                  t =3D xre * xre - xim * xim;
>                  xim =3D xre * xim + xre * xim;
>                  xre =3D t;
>                  //...=3Dc;
>                  xre +=3D cre;
>                  xim +=3D cim;
>                  //if(x.AbsoluteSquared>4)
>                  if (xre * xre + xim * xim > 4)
>                      return i;
>              }
>              return -1;
>          }
>          static void Main(string[] args)
>          {
>              DateTime time0, time1;
>              TimeSpan delta0, delta1;
>              Complex x=3DComplex.Zero;
>              time0 =3D DateTime.Now;
>              for (int i =3D 0; i < 10000; i++)
>                  MandelbrotIteration1(x);
>              delta0 =3D DateTime.Now - time0;
>              time1 =3D DateTime.Now;
>              for (int i =3D 0; i < 10000; i++)
>                  MandelbrotIteration4(x);
>              delta1 =3D DateTime.Now - time1;
>              Console.WriteLine("Relying on the JIT to inline: {0}", delta=
0);
>              Console.WriteLine("Manually inlined like in the bad old
> days {0}:", delta1);
>              Console.ReadLine();
>          }
>      }
> }
> _______________________________________________
> Mono-list maillist  -  Mono-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
>