[Mono-list] Performance benchmark

Miguel de Icaza miguel at novell.com
Sun Feb 28 13:37:59 EST 2010


>
> I looked a little bit into this, and although the above looks
> computationally intensive, in Mono the above goes through vast paths of GC
> bound operations as our implementation for the Decimal (double) sadly goes
> through a very inefficient code path.   It allocates strings, formats
> strings and does a bunch of extra work.
>
> We probably should implement a Decimal constructor that decodes
> double/floats directly.
>

It seems like we used to have this support, but it was replaced by the
slower code path in 2004 to fix some bug (r29795), this is what I was able
to put together.   The slow code path that basically turns a double into a
string, and then parses the string as a decimal was committed with this
message:

        * Decimal.cs: Fixed regression in System.Data caused by the recent
        changes. Adapted (and moved) the code to correct the scale from
        SqlMoney.

The commit made two changes, one was the part of the "Fixed regression" that
was introduced on 29625, the source of the problem seems to have been
"correct the scale from SqlMoney", the comment on the actual change was:

+ // we must respect the precision (double2decimal doesn't)

A change to SqlMoney the day after showed that a hack was removed from
SqlMoney since Decimal had been fixed:

http://lists.ximian.com/archives/public/mono-patches/2004-June/041056.html

The actual patch was:

diff -u -d -r1.15 -r1.16
--- SqlMoney.cs 16 Jun 2004 13:50:41 -0000 1.15
+++ SqlMoney.cs 17 Jun 2004 18:46:45 -0000 1.16
@@ -57,23 +57,7 @@
  {
  if (value > 922337203685477.5807m || value < -922337203685477.5808m)
  throw new OverflowException ();
-
- value = Decimal.Round (value, 4);
-
- int [] bits = Decimal.GetBits (value);
- int scaleDiff = 4 - ((bits [3] & 0x7FFF0000) >> 16);
- decimal tmp = value;
- // integrify
- if (scaleDiff > 0)
- for (int i = 0; i < scaleDiff; i++)
- tmp *= 10;
- else if (scaleDiff < 0)
- for (int i = 0; i > scaleDiff; i--)
- tmp /= 10;
- int [] tmpbits = decimal.GetBits (tmp);
- tmpbits [3] = (value < 0) ? 0x8004 << 16 : 0x40000;
- this.value = new decimal (tmpbits);
-
+ this.value = Decimal.Round (value, 4);
  notNull = true;
  }

I can not find a report of what exactly failed with SqlMoney at the time,
but it might be worth looking again at reusing the unmanaged conversion
routine and running the tests again.   There is one puzzling bit: what is
the "digits" parameter for?

Miguel.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-list/attachments/20100228/3ace5d74/attachment.html 


More information about the Mono-list mailing list