Optimizing the use of the method IsNan. Bottleneck for large numbers of coordinates.

Oct 30, 2011 at 11:59 AM

 

I use a very large list of coordinates. About 10,000 and more. When I increase the scale of maps to show a small area, the processing takes a very long time (30-60 seconds!). 
In the profiler I found that a lot of time spent on call to "Coordinate.Equals". This method and all others use "double.IsNan". I learned this method in NetReflector, that's what I saw: 

 
public static bool IsNaN (double f)
{
	return (f! = f);
}


for each test time is wasted calling simply for comparison. 
I wrote a program to study the performance, the result is stunning! 

For x86 
Count: 100 million 
IsNaN: 00:08.8405057 
a! = n: 00:08.4684843 
d%: -4.208% 

For x64 
Count: 1 billion 
IsNaN: 00:04.9612838 
a! = n: 00:03.4391967 
d%: -30.679% 

Throughout the library IsNaN used very often and when to use it instead of "x! = x" then you can get a performance boost. 

P.S. I understand that the visibility in this case falls very much, but optimization, sooner or later need.
I used the following code to check for

 

   static void Main(string[] args)
        {
            int count = 100000000;
            bool isNaN0;
            bool isNaN1;
            bool eq0;
            bool eq1;
            double a = 1.111;
            double n = double.NaN;

            DateTime t0 = DateTime.Now;

            isNaN0 = double.IsNaN(a);
            isNaN1 = double.IsNaN(n);
            for(int i = 0; i < count; i++)
            {
                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);
                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);
                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);
                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);
                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);

                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);
                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);
                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);
                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);
                isNaN0 = double.IsNaN(a); isNaN1 = double.IsNaN(n);
            }

            DateTime t1 = DateTime.Now;

            eq0 = (a != a);
            eq1 = (n != n);
            for(int i = 0; i < count; i++)
            {
                eq0 = (a != a); eq1 = (n != n);
                eq0 = (a != a); eq1 = (n != n);
                eq0 = (a != a); eq1 = (n != n);
                eq0 = (a != a); eq1 = (n != n);
                eq0 = (a != a); eq1 = (n != n);

                eq0 = (a != a); eq1 = (n != n);
                eq0 = (a != a); eq1 = (n != n);
                eq0 = (a != a); eq1 = (n != n);
                eq0 = (a != a); eq1 = (n != n);
                eq0 = (a != a); eq1 = (n != n);
            }

            DateTime t2 = DateTime.Now;

            TimeSpan d1 = t1 - t0;
            TimeSpan d2 = t2 - t1;
            double dd1 = d1.Ticks;
            double dd2 = d2.Ticks;

            Console.WriteLine("Count:" + (count*10).ToString("### ### ### ###"));
            Console.WriteLine("IsNaN:" + d1.ToString());
            Console.WriteLine("a!=n :" + d2.ToString());
            Console.WriteLine("d%   :" + (100 * (dd2 - dd1) / dd1).ToString("#0.000") + "%");
            Console.WriteLine();
            Console.WriteLine("IsNaN for not NaN:" + isNaN0.ToString());
            Console.WriteLine("IsNaN for NaN    :" + isNaN1.ToString());
            Console.WriteLine("!= for not NaN   :" + eq0.ToString());
            Console.WriteLine("!= for NaN       :" + eq1.ToString());

            Console.ReadKey();

        }