C# 与平面数组相比,.Net中的简单字典查找速度较慢
我发现与平面阵列访问相比,字典查找可能非常慢。知道为什么吗?我正在使用Ants Profiler进行性能测试。下面是重现问题的示例函数:C# 与平面数组相比,.Net中的简单字典查找速度较慢,c#,performance,C#,Performance,我发现与平面阵列访问相比,字典查找可能非常慢。知道为什么吗?我正在使用Ants Profiler进行性能测试。下面是重现问题的示例函数: private static void NodeDisplace() { var nodeDisplacement = new Dictionary<double, double[]>(); var times = new List<double>(); for (int
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++;
}
}
}
private static void NodeDisplace()
{
var nodeDisplacement=新字典();
var times=新列表();
对于(int i=0;i<6000;i++)
{
加上(i*0.02);
}
foreach(以时间为单位的var时间)
{
nodeDisplacement.Add(时间,新的双精度[6]);
}
变量5=5;
var 6=6;
int模式=10;
var arrayList=new double[times.Count*6];
对于(int i=0;i
注意平面数组访问和字典访问之间的相对大小?考虑到数组索引操作(6*k+j
),平面数组的速度大约是字典访问速度(0.403/0.0278)的20倍
听起来很奇怪,但字典查找占用了我大部分时间,我必须优化它 是的,我一点也不惊讶。字典的意义在于它们被用来查找任意键。考虑单个数组引用的发生:
- 检查边界
- 将索引乘以元素大小
- 向指针添加索引
- 可能会检查密钥是否为空
- 获取密钥的哈希代码
- 为该哈希代码找到正确的插槽(可能是“mod prime”操作)
- 可能取消对数组元素的引用以查找该插槽的信息
- 比较散列码
- 如果哈希代码匹配,比较是否相等(并可能继续进行下一个哈希代码匹配)
double
值查找(而不是等距的双精度,因此可以轻松映射为整数)
我想说你的标题有误导性——不是字典查找速度慢,而是当数组是一种更合适的方法时,它们的速度快得离谱。此外,我想补充一点,你的内部循环做得不多,通常,您在内部循环中至少多做一些工作,然后字典的相对性能损失就会有所降低
如果查看Reflector中的Double.GetHashCode()
代码,您会发现它正在执行4行代码(假设Double不是0),只是这比内部循环的主体要多Dictionary.Insert()
(由集合索引器调用)是更多的代码,几乎满屏
与平面数组相比,Dictionary的优点在于,当键不密集(就像您的情况一样)并且读写类似于~O(1)数组(但具有更高的常数)时,不会浪费太多内存
作为旁注,您可以使用多维数组而不是6*k+j
技巧。这样说吧
var arrayList = new double[times.Count, 6];
arrayList[k ,j] = simpelCompute;
这样使用它
var arrayList = new double[times.Count, 6];
arrayList[k ,j] = simpelCompute;
它不会更快,但更易于阅读。但索引访问通常比哈希查找更快。。。“你说奇怪是什么意思?”米奇用蚂蚁量了量Profiler@Nick,但有20倍的不同?@Ngu:当然。还有很多工作要做。阵列访问是CPU的绝对天赋——它几乎不需要做任何事情。你不是在拿苹果和桔子做比较吗?用于字典和数组访问的索引不同。当然,使用整数索引访问数组比使用任意类型(
double
)访问字典要快。与在其他代码中只进行一次数组访问相比,您的字典访问会进行额外的数组访问。因子20听起来不错,因为数组访问基本上不需要任何成本。我使用的是均匀间隔的double
(参见上面的代码),但它仍然很慢。@Ngu:这是我的观点-您使用的范围很容易映射到整数,所以使用数组代替。为作业使用最合适的数据结构—在本例中为数组。