Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by MrPhil · Mar 03, 2014 at 06:19 PM · performancememoryconvert

Why does Convert.ToDecimal use Double.ToString internally?

I'm focused on improving the performance of a project and noticed this very strange behavior. When converting a Double to a Decimal, internally, the Convert code calls on Double.ToString!?! This actually is throwing off a fair amount of memory in my project because it gets called 30-40 times a frame. I can probably refactor away from using the Convert, but this internal behavior really surprises me.

 Convert.ToDecimal(theDouble);

The Profiler: alt text

convert.todecimal.png (36.9 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by whydoidoit · Mar 03, 2014 at 06:30 PM

Well this is the code that Decimal uses to convert a double in the version we get with Unity:

 /// <summary>
 /// Initializes a new instance of <see cref="T:System.Decimal"/> to the value of the specified double-precision floating-point number.
 /// </summary>
 /// <param name="value">The value to represent as a <see cref="T:System.Decimal"/>. </param><exception cref="T:System.OverflowException"><paramref name="value"/> is greater than <see cref="F:System.Decimal.MaxValue"/> or less than <see cref="F:System.Decimal.MinValue"/>.-or- <paramref name="value"/> is <see cref="F:System.Double.NaN"/>, <see cref="F:System.Double.PositiveInfinity"/>, or <see cref="F:System.Double.NegativeInfinity"/>. </exception>
 public Decimal(double value)
 {
   if (value > 7.92281625142643E+28 || value < -7.92281625142643E+28 || (double.IsNaN(value) || double.IsNegativeInfinity(value)) || double.IsPositiveInfinity(value))
   {
     string fmt = "Value {0} is greater than Decimal.MaxValue or less than Decimal.MinValue";
     object[] objArray = new object[1];
     int index = 0;
     // ISSUE: variable of a boxed type
     __Boxed<double> local = (ValueType) value;
     objArray[index] = (object) local;
     throw new OverflowException(Locale.GetText(fmt, objArray));
   }
   else
   {
     Decimal num = Decimal.Parse(value.ToString((IFormatProvider) CultureInfo.InvariantCulture), NumberStyles.Float, (IFormatProvider) CultureInfo.InvariantCulture);
     this.flags = num.flags;
     this.hi = num.hi;
     this.lo = num.lo;
     this.mid = num.mid;
   }
 }

And here is the heart of the parser:

 private static bool PerformParse(string s, NumberStyles style, IFormatProvider provider, out Decimal res, bool throwex)
 {
   NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
   int decPos;
   bool isNegative;
   bool expFlag;
   int exp;
   s = Decimal.stripStyles(s, style, instance, out decPos, out isNegative, out expFlag, out exp, throwex);
   if (s == null)
   {
     res = new Decimal(0);
     return false;
   }
   else if (decPos < 0)
   {
     if (throwex)
       throw new Exception(Locale.GetText("Error in System.Decimal.Parse"));
     res = new Decimal(0);
     return false;
   }
   else
   {
     int length1 = s.Length;
     int startIndex = 0;
     while (startIndex < decPos && (int) s[startIndex] == 48)
       ++startIndex;
     if (startIndex > 1 && length1 > 1)
     {
       s = s.Substring(startIndex, length1 - startIndex);
       decPos -= startIndex;
     }
     int length2 = decPos != 0 ? 28 : 27;
     int length3 = s.Length;
     if (length3 >= length2 + 1 && string.Compare(s, 0, "79228162514264337593543950335", 0, length2 + 1, false, CultureInfo.InvariantCulture) <= 0)
       ++length2;
     if (length3 > length2 && decPos < length3)
     {
       int num1 = (int) s[length2] - 48;
       s = s.Substring(0, length2);
       bool flag = false;
       if (num1 > 5)
         flag = true;
       else if (num1 == 5)
         flag = isNegative || ((int) s[length2 - 1] - 48 & 1) == 1;
       if (flag)
       {
         char[] chArray = s.ToCharArray();
         int index;
         for (index = length2 - 1; index >= 0; chArray[index--] = '0')
         {
           int num2 = (int) chArray[index] - 48;
           if ((int) chArray[index] != 57)
           {
             chArray[index] = (char) (num2 + 49);
             break;
           }
         }
         if (index == -1 && (int) chArray[0] == 48)
         {
           ++decPos;
           s = "1".PadRight(decPos, '0');
         }
         else
           s = new string(chArray);
       }
     }
     Decimal val;
     if (Decimal.string2decimal(out val, s, (uint) decPos, 0) != 0)
     {
       if (throwex)
         throw new OverflowException();
       res = new Decimal(0);
       return false;
     }
     else if (expFlag && Decimal.decimalSetExponent(ref val, exp) != 0)
     {
       if (throwex)
         throw new OverflowException();
       res = new Decimal(0);
       return false;
     }
     else
     {
       if (isNegative)
         val.flags ^= (uint) int.MinValue;
       res = val;
       return true;
     }
   }
 }


It's a very simple implementation and it is different to the current .NET version. I guess the question is - can you get away without using Decimals - they're pretty expensive even without this.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image whydoidoit · Mar 03, 2014 at 06:33 PM 1
Share

It's going to cause Garbage Collection for sure.

avatar image whydoidoit · Mar 03, 2014 at 06:35 PM 1
Share

By the way - I strongly suggest getting hold of a decompiler when you are looking at this stuff, it's the only way to know what is really going on. I use dotPeek from JetBrains.

avatar image MrPhil · Mar 03, 2014 at 06:48 PM 0
Share

Thanks! I've never really gotten into the decompiler stuff. Thanks for confir$$anonymous$$g what I suspected.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Memory Managmenet 1 Answer

Performance and memory 1 Answer

Reasonable heap alloc. per second and total ? 0 Answers

(Solved) What is done in preloading ( Application.LoadLevel(x) ) 2 Answers

UI-based game memory and performance issue. 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges