Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Dictionary Lookup is Slow in .Net Compared to Flat Array

Tags:

performance

c#

I found that dictionary lookup could be very slow if compared to flat array access. Any idea why? I'm using Ants Profiler for performance testing. Here's a sample function that reproduces the problem:

    private static void NodeDisplace()
    {
        var nodeDisplacement = new Dictionary<double, double[]>();

        var times = new List<double>();
        for (int i = 0; i < 6000; i++)
        {
            times.Add(i * 0.02);
        }
        foreach (var time in times)
        {
            nodeDisplacement.Add(time, new double[6]);
        }

        var five = 5;
        var six = 6;
        int modes = 10;
        var arrayList = new double[times.Count*6];
        for (int i = 0; i < modes; i++)
        {
            int k=0;
            foreach (var time in times)
            {
                for (int j = 0; j < 6; j++)
                {

                    var simpelCompute = five * six;  // 0.027 sec
                    nodeDisplacement[time][j] = simpelCompute;  //0.403 sec
                    arrayList[6*k+j] = simpelCompute;  //0.0278 sec
                }

                k++;
            }
        }
    }

Notice the relative magnitude between flat array access and dictionary access? Flat array is about 20 times faster than dictionary access ( 0.403/0.0278), after taking into account of the array index manipulation ( 6*k+j).

As weird as it sounds, but dictionary lookup is taking a major portion of my time, and I have to optimize it.

like image 597
Graviton Avatar asked Dec 03 '22 10:12

Graviton


1 Answers

Yes, I'm not surprised. The point of dictionaries is that they're used to look up arbitrary keys. Consider what has to happen for a single array dereference:

  • Check bounds
  • Multiply index by element size
  • Add index to pointer

Very, very fast. Now for a dictionary lookup (very rough; depends on implementation):

  • Potentially check key for nullity
  • Take hash code of key
  • Find the right slot for that hash code (probably a "mod prime" operation)
  • Probably dereference an array element to find the information for that slot
  • Compare hash codes
  • If the hash codes match, compare for equality (and potentially go on to the next hash code match)

If you've got "keys" which can very easily be used as array indexes instead (e.g. contiguous integers, or something which can easily be mapped to contiguous integers) then that will be very, very fast. That's not the primary use case for hash tables. They're good for situations which can't easily be mapped that way - for example looking up by string, or by arbitrary double value (rather than doubles which are evenly spaced, and can thus be mapped to integers easily).

I would say that your title is misleading - it's not that dictionary lookup is slow, it's that when arrays are a more suitable approach, they're ludicrously fast.

like image 149
Jon Skeet Avatar answered Jan 07 '23 11:01

Jon Skeet