使用两个整数键存储信息的最快方法是什么?

时间:2015-12-06 02:39:45

标签: c# performance

我有大量的对象,它们有两个Int32来识别它们在集合中。问题是收集的选择。唯一的标准是纯粹的性能,用于访问/“读取”对象(无需可写)。

我分析的东西:

我没有尝试this的哈希表原因。 我有想法尝试以下类型:

Dictionary<Tuple<int,int>,object>
Dictionary<long,object> // putting the bytes of two ints together by first*(int.MaxValue+1L)+second
Dictionary<int, List<Tuple<int,object>>
Dictionary<int, Dictionary<int,object>>


List<Tuple<int,int,object>>
List<Tuple<long,object>>
List<Tuple<int,Tuple<int,object>>

我为第一个填充了1000个值,为第二个整数填充了100个值。测试的“对象”是firstInt.ToString()+secondInt.ToString()

我使用以下模式进行测量:

        System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
        bool b=true;
        st.Start();
        for(int i=0;i<100;i++)
        {
            for (int ii = 0; ii< 1000; ii++)
            {   //for making sure code optimization doesn't jump over it
                b=b&*accessor*.Contains('a');
            }
        }
        st.Stop();
        Console.WriteLine("Result: "+st.ElapsedMilliseconds);

我使用了以下访问者:

     Dictionary<Tuple<int,int>,object> dir [...]
     Accessor:  dir[a][b]
     Result: 211ms

     Dictionary<long,object> dir [...]
     Accessor: dir[merge(a,b)]
     Result: 70ms

     //method for sticking two ints together
     public static long merge(int a,int b)
     { return (int.MaxValue+1L)*a+b;}

     Dictionary<int, List<Tuple<int,object>> dir[...]
     Accessor:   dir[a].Find(x=>x.Item1==b).Item2
     Result:  15ms

     Dictionary<int, Dictionary<int,object>> dir[...]
     Accessor:   dir[a][b]
     Result:  22ms

     List<Tuple<int,int,object>> dir[...]
     Accessor: dir.Find(x=>x.Item1==a&&x.Item2==b).Item3
     Result: over60s

     List<Tuple<long,object>> dir[...]
     Accessor: dir.Find(x=>x.Item1==merge(a,b)).Item2
     Result: over60s

     List<Tuple<int,Tuple<int,object>> dir[...]
     Accessor: dir.Find(x=>x.Item==a).Item2.Find(x=>x.Item==b).Item2
     Result: over60s

是否有更好/更快的类型?有关改善表现的任何建议?或者是否有一种完全不同的解决方案最先进的技术?

1 个答案:

答案 0 :(得分:2)

从技术上讲,你的第二种方法(Dictionary<long,object>)应该是最快的。我认为最大的问题是方法调用的开销(可能没有被JIT内联)。还有一种更快的方法可以从两个int值中获得组合long

而不是这样做

Accessor: dir[merge(a,b)]

试试这个:

Accessor: dir[(((ulong)(uint)a) << 32) | (uint) b)]

另外,根据@ JoelCoehoorn在下面的评论,您可以将合并过程提取到单独的方法中,并使用以下属性强制内联:https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions(v=VS.110).aspx。但是,我使用两种方式运行基准测试只是为了确保没有副作用。

请在评论中发布速度结果;我非常好奇。