Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is C# Array.BinarySearch so fast?

I have implemented a very simple binarySearch implementation in C# for finding integers in an integer array:

Binary Search

static int binarySearch(int[] arr, int i)
{
    int low = 0, high = arr.Length - 1, mid;

    while (low <= high)
    {
        mid = (low + high) / 2;

        if (i < arr[mid])
            high = mid - 1;

        else if (i > arr[mid])
            low = mid + 1;

        else
            return mid;
    }
    return -1;
}

When comparing it to C#'s native Array.BinarySearch() I can see that Array.BinarySearch() is more than twice as fast as my function, every single time.

MSDN on Array.BinarySearch:

Searches an entire one-dimensional sorted array for a specific element, using the IComparable generic interface implemented by each element of the Array and by the specified object.

What makes this approach so fast?

Test code

using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        Random rnd = new Random();
        Stopwatch sw = new Stopwatch();

        const int ELEMENTS = 10000000;
        int temp;

        int[] arr = new int[ELEMENTS];

        for (int i = 0; i < ELEMENTS; i++)
            arr[i] = rnd.Next(int.MinValue,int.MaxValue);

        Array.Sort(arr);

        // Custom binarySearch

        sw.Restart();
        for (int i = 0; i < ELEMENTS; i++)
            temp = binarySearch(arr, i);
        sw.Stop();

        Console.WriteLine($"Elapsed time for custom binarySearch: {sw.ElapsedMilliseconds}ms");

        // C# Array.BinarySearch

        sw.Restart();
        for (int i = 0; i < ELEMENTS; i++)
            temp = Array.BinarySearch(arr,i);
        sw.Stop();

        Console.WriteLine($"Elapsed time for C# BinarySearch: {sw.ElapsedMilliseconds}ms");
    }

    static int binarySearch(int[] arr, int i)
    {
        int low = 0, high = arr.Length - 1, mid;

        while (low <= high)
        {
            mid = (low+high) / 2;

            if (i < arr[mid])
                high = mid - 1;

            else if (i > arr[mid])
                low = mid + 1;

            else
                return mid;
        }
        return -1;
    }
}

Test results

+------------+--------------+--------------------+
| Attempt No | binarySearch | Array.BinarySearch |
+------------+--------------+--------------------+
|          1 | 2700ms       | 1099ms             |
|          2 | 2696ms       | 1083ms             |
|          3 | 2675ms       | 1077ms             |
|          4 | 2690ms       | 1093ms             |
|          5 | 2700ms       | 1086ms             |
+------------+--------------+--------------------+
like image 307
Daniel Avatar asked Aug 08 '16 20:08

Daniel


1 Answers

Your code is faster when run outside Visual Studio:

Yours vs Array's:

From VS - Debug mode: 3248 vs 1113
From VS - Release mode: 2932 vs 1100
Running exe - Debug mode: 3152 vs 1104
Running exe - Release mode: 559 vs 1104

Array's code might be already optimized in the framework but also does a lot more checking than your version (for instance, your version may overflow if arr.Length is greater than int.MaxValue / 2) and, as already said, is designed for a wide range of types, not just int[].

So, basically, it's slower only when you are debugging your code, because Array's code is always run in release and with less control behind the scenes.

like image 71
Andrew Avatar answered Nov 12 '22 21:11

Andrew